import { NoticeType } from '../../types/users';
import { getFacet } from '../issues';
import {
- bulkActivateRules,
- bulkDeactivateRules,
Profile,
- searchQualityProfiles,
SearchQualityProfilesParameters,
SearchQualityProfilesResponse,
+ bulkActivateRules,
+ bulkDeactivateRules,
+ searchQualityProfiles,
} from '../quality-profiles';
import { getRuleDetails, getRulesApp, searchRules, updateRule } from '../rules';
import { dismissNotice, getCurrentUser } from '../users';
interface FacetFilter {
languages?: string;
+ available_since?: string;
}
const FACET_RULE_MAP: { [key: string]: keyof Rule } = {
],
}),
mockRuleDetails({
+ createdAt: '2022-12-16T17:26:54+0100',
key: 'rule8',
type: 'VULNERABILITY',
lang: 'py',
this.rules = cloneDeep(this.defaultRules);
}
- getRuleWithoutDetails() {
- return this.rules.map((r) =>
+ getRulesWithoutDetails(rules: RuleDetails[]) {
+ return rules.map((r) =>
pick(r, [
'isTemplate',
'key',
);
}
- filterFacet({ languages }: FacetFilter) {
- let filteredRules = this.getRuleWithoutDetails();
+ filterFacet({ languages, available_since }: FacetFilter) {
+ let filteredRules = this.rules;
if (languages) {
filteredRules = filteredRules.filter((r) => r.lang && languages.includes(r.lang));
}
- return filteredRules;
+ if (available_since) {
+ filteredRules = filteredRules.filter(
+ (r) => r.createdAt && new Date(r.createdAt) > new Date(available_since)
+ );
+ }
+ return this.getRulesWithoutDetails(filteredRules);
}
setIsAdmin() {
return this.reply(rule);
};
- handleSearchRules = ({ facets, languages, p, ps, rule_key }: SearchRulesQuery) => {
+ handleSearchRules = ({
+ facets,
+ languages,
+ p,
+ ps,
+ available_since,
+ rule_key,
+ }: SearchRulesQuery) => {
const countFacet = (facets || '').split(',').map((facet: keyof Rule) => {
const facetCount = countBy(
this.rules.map((r) => r[FACET_RULE_MAP[facet] || facet] as string)
const currentP = p || 1;
let filteredRules: Rule[] = [];
if (rule_key) {
- filteredRules = this.getRuleWithoutDetails().filter((r) => r.key === rule_key);
+ filteredRules = this.getRulesWithoutDetails(this.rules).filter((r) => r.key === rule_key);
} else {
- filteredRules = this.filterFacet({ languages });
+ filteredRules = this.filterFacet({ languages, available_since });
}
const responseRules = filteredRules.slice((currentP - 1) * currentPs, currentP * currentPs);
return this.reply({
issue: mockRawIssue(false, {
key: 'issue11',
component: 'foo:test1.js',
+ creationDate: '2022-01-01T09:36:01+0100',
message: 'FlowIssue',
characteristic: IssueCharacteristic.Clear,
type: IssueType.CodeSmell,
.filter((item) => !query.rules || query.rules.split(',').includes(item.issue.rule))
.filter(
(item) => !query.resolutions || query.resolutions.split(',').includes(item.issue.resolution)
+ )
+ .filter(
+ (item) =>
+ !query.inNewCodePeriod || new Date(item.issue.creationDate) > new Date('2023-01-10')
);
// Splice list items according to paging using a fixed page size
*/
import { fireEvent, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { byRole } from 'testing-library-selector';
+import { byPlaceholderText, byRole } from 'testing-library-selector';
import CodingRulesMock from '../../../api/mocks/CodingRulesMock';
import { mockCurrentUser, mockLoggedInUser } from '../../../helpers/testMocks';
import { renderAppRoutes } from '../../../helpers/testReactTestingUtils';
jest.mock('../../../api/quality-profiles');
const ui = {
+ rulesList: byRole('list', { name: 'list_of_rules' }),
activateInSelectOption: byRole('combobox', { name: 'coding_rules.activate_in' }),
deactivateInSelectOption: byRole('combobox', { name: 'coding_rules.deactivate_in' }),
+ availableSinceFacet: byRole('button', { name: 'coding_rules.facet.available_since' }),
+ availableSinceDateField: byPlaceholderText('date'),
};
let handler: CodingRulesMock;
).not.toBeInTheDocument();
});
+it('should filter correctly', async () => {
+ const user = userEvent.setup();
+ renderCodingRulesApp(mockCurrentUser());
+
+ expect(await within(await ui.rulesList.find()).findAllByRole('listitem')).toHaveLength(8);
+ await user.click(await ui.availableSinceFacet.find());
+ await user.click(await ui.availableSinceDateField.find());
+ await userEvent.selectOptions(
+ await screen.findByRole('combobox', { name: 'Month:' }),
+ 'November'
+ );
+ await userEvent.selectOptions(screen.getByRole('combobox', { name: 'Year:' }), '2022');
+ await user.click(screen.getByRole('gridcell', { name: '1' }));
+ expect(ui.availableSinceDateField.get()).toHaveDisplayValue('Nov 1, 2022');
+ // eslint-disable-next-line jest-dom/prefer-in-document
+ expect(within(ui.rulesList.get()).getAllByRole('listitem')).toHaveLength(1);
+});
+
function renderCodingRulesApp(currentUser?: CurrentUser, navigateTo?: string) {
renderAppRoutes('coding_rules', routes, {
navigateTo,
}
class AvailableSinceFacet extends React.PureComponent<Props & WrappedComponentProps> {
+ property: keyof Query = 'availableSince';
+
handleHeaderClick = () => {
- this.props.onToggle('availableSince');
+ this.props.onToggle(this.property);
};
handleClear = () => {
render() {
const { open, value } = this.props;
+ const headerId = `facet_${this.property}`;
return (
- <FacetBox property="availableSince">
+ <FacetBox property={this.property}>
<FacetHeader
+ id={headerId}
name={translate('coding_rules.facet.available_since')}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
import { Dict, Paging, RawQuery, Rule, RuleActivation } from '../../../types/types';
import { CurrentUser, isLoggedIn } from '../../../types/users';
import {
+ STANDARDS,
shouldOpenSonarSourceSecurityFacet,
shouldOpenStandardsChildFacet,
shouldOpenStandardsFacet,
- STANDARDS,
} from '../../issues/utils';
import {
Activation,
Actives,
- areQueriesEqual,
FacetKey,
Facets,
+ OpenFacets,
+ Query,
+ areQueriesEqual,
getAppFacet,
getOpen,
getSelected,
getServerFacet,
hasRuleKey,
- OpenFacets,
parseQuery,
- Query,
serializeQuery,
shouldRequestFacet,
} from '../query';
/>
) : (
<>
- <h2 className="a11y-hidden">{translate('list_of_rules')}</h2>
- <ul>
+ <ul aria-label={translate('list_of_rules')}>
{rules.map((rule) => (
<RuleListItem
activation={this.getRuleActivation(rule.key)}
(key) => -stats[key],
(key) => renderTextName(key).toLowerCase()
));
+ const headerId = `facet_${property}`;
return (
<FacetBox
property={property}
>
<FacetHeader
+ id={headerId}
name={translate('coding_rules.facet', property)}
disabled={disabled}
disabledHelper={disabledHelper}
</FacetHeader>
{open && items !== undefined && (
- <FacetItemsList label={property}>{items.map(this.renderItem)}</FacetItemsList>
+ <FacetItemsList labelledby={headerId}>{items.map(this.renderItem)}</FacetItemsList>
)}
{open && this.props.renderFooter !== undefined && this.props.renderFooter()}
);
const property = 'profile';
+ const headerId = `facet_${property}`;
return (
<FacetBox property={property}>
<FacetHeader
+ id={headerId}
name={translate('coding_rules.facet.qprofile')}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
/>
</FacetHeader>
- {open && <FacetItemsList label={property}>{profiles.map(this.renderItem)}</FacetItemsList>}
+ {open && (
+ <FacetItemsList labelledby={headerId}>{profiles.map(this.renderItem)}</FacetItemsList>
+ )}
</FacetBox>
);
}
<div
className="layout-page-main-inner"
>
- <h2
- className="a11y-hidden"
+ <ul
+ aria-label="list_of_rules"
>
- list_of_rules
- </h2>
- <ul>
<RuleListItem
isLoggedIn={true}
key="javascript:S1067"
<div
className="layout-page-main-inner"
>
- <h2
- className="a11y-hidden"
- >
- list_of_rules
- </h2>
- <ul />
+ <ul
+ aria-label="list_of_rules"
+ />
</div>
</main>
</div>
const { domain, open } = this.props;
const helperMessageKey = `component_measures.domain_facets.${domain.name}.help`;
const helper = hasMessage(helperMessageKey) ? translate(helperMessageKey) : undefined;
+ const headerId = `facet_${domain.name}`;
return (
<FacetBox property={domain.name}>
<FacetHeader
helper={helper}
+ id={headerId}
name={getLocalizedMetricDomain(domain.name)}
onClick={this.handleHeaderClick}
open={open}
/>
{open && (
- <FacetItemsList label={domain.name}>
+ <FacetItemsList labelledby={headerId}>
{this.renderOverviewFacet()}
{this.renderItemsFacet()}
</FacetItemsList>
const facetName = translate('component_measures.overview', value, 'facet');
return (
<FacetBox property={value}>
- <FacetItemsList label={value}>
+ <FacetItemsList label={facetName}>
<FacetItem
active={value === selected}
key={value}
>
<FacetHeader
helper="component_measures.domain_facets.Reliability.help"
+ id="facet_Reliability"
name="Reliability"
onClick={[Function]}
open={true}
values={[]}
/>
<FacetItemsList
- label="Reliability"
+ labelledby="facet_Reliability"
>
<FacetItem
active={false}
>
<FacetHeader
helper="component_measures.domain_facets.Reliability.help"
+ id="facet_Reliability"
name="Reliability"
onClick={[Function]}
open={true}
}
/>
<FacetItemsList
- label="Reliability"
+ labelledby="facet_Reliability"
>
<FacetItem
active={false}
>
<FacetHeader
helper="component_measures.domain_facets.Reliability.help"
+ id="facet_Reliability"
name="Reliability"
onClick={[Function]}
open={true}
values={[]}
/>
<FacetItemsList
- label="Reliability"
+ labelledby="facet_Reliability"
>
<FacetItem
active={false}
>
<FacetHeader
helper="component_measures.domain_facets.Reliability.help"
+ id="facet_Reliability"
name="Reliability"
onClick={[Function]}
open={true}
values={[]}
/>
<FacetItemsList
- label="Reliability"
+ labelledby="facet_Reliability"
>
<FacetItem
active={false}
).toHaveTextContent('ts674');
});
});
+
+ it('should show the new code issues only', async () => {
+ const user = userEvent.setup();
+
+ renderProjectIssuesApp('project/issues?id=myproject');
+
+ expect(await ui.issueItems.findAll()).toHaveLength(7);
+ await user.click(await ui.inNewCodeFilter.find());
+ expect(await ui.issueItems.findAll()).toHaveLength(6);
+ });
});
describe('issues item', () => {
.filter(([, value]) => value === fitFor)
.map(([key]) => key as IssueCharacteristic);
+ const headerId = `facet_${this.property}_${fitFor}`;
+
return (
<FacetBox property={this.property}>
<FacetHeader
fetching={this.props.fetching}
+ id={headerId}
name={translate('issues.facet.characteristics', fitFor)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
{this.props.open && (
<>
- <FacetItemsList label={this.property}>
+ <FacetItemsList labelledby={headerId}>
{availableCharacteristics.map(this.renderItem)}
</FacetItemsList>
<MultipleSelectionHint
render() {
const { forceShow, open, fetching } = this.props;
const values = this.getValues();
+ const headerId = `facet_${this.property}`;
if (values.length < 1 && !forceShow) {
return null;
<FacetBox property={this.property}>
<FacetHeader
fetching={fetching}
+ id={headerId}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
return (
<FacetBox property={PROPERTY}>
- <FacetItemsList label={PROPERTY}>
+ <FacetItemsList label={translate('issues.facet', PROPERTY)}>
<FacetItem
active={newCodeSelected}
loading={fetching}
render() {
const { resolutions, stats = {}, forceShow, fetching, open } = this.props;
const values = resolutions.map((resolution) => this.getFacetItemName(resolution));
+ const headerId = `facet_${this.property}`;
if (values.length < 1 && !forceShow) {
return null;
<FacetBox property={this.property}>
<FacetHeader
fetching={fetching}
+ id={headerId}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
{open && (
<>
- <FacetItemsList label={this.property}>
+ <FacetItemsList labelledby={headerId}>
{RESOLUTIONS.map(this.renderItem)}
</FacetItemsList>
<MultipleSelectionHint
const values = scopes.map((scope) => translate('issue.scope', scope));
const property = 'scopes';
+ const headerId = `facet_${property}`;
if (values.length < 1 && !forceShow) {
return null;
}
<FacetBox property={property}>
<FacetHeader
fetching={fetching}
+ id={headerId}
name={translate('issues.facet.scopes')}
onClear={() => props.onChange({ scopes: [] })}
onClick={() => props.onToggle('scopes')}
{open && (
<>
- <FacetItemsList label={property}>
+ <FacetItemsList labelledby={headerId}>
{SOURCE_SCOPES.map(({ scope, qualifier }) => {
const active = scopes.includes(scope);
const stat = stats[scope];
render() {
const { fetching, open, severities, stats = {} } = this.props;
const values = severities.map((severity) => translate('severity', severity));
+ const headerId = `facet_${this.property}`;
return (
<FacetBox property={this.property}>
<FacetHeader
fetching={fetching}
+ id={headerId}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
{open && (
<>
- <FacetItemsList label={this.property}>{SEVERITIES.map(this.renderItem)}</FacetItemsList>
+ <FacetItemsList labelledby={headerId}>{SEVERITIES.map(this.renderItem)}</FacetItemsList>
<MultipleSelectionHint options={Object.keys(stats).length} values={severities.length} />
</>
)}
];
};
+ getFacetHeaderId = (property: string) => {
+ return `facet_${property}`;
+ };
+
handleHeaderClick = () => {
this.props.onToggle(this.property);
};
stats: any,
values: string[],
categories: string[],
- listLabel: ValuesProp,
+ listKey: ValuesProp,
renderName: (standards: Standards, category: string) => React.ReactNode,
renderTooltip: (standards: Standards, category: string) => string,
onClick: (x: string, multiple?: boolean) => void
};
return (
- <FacetItemsList label={listLabel}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(listKey)}>
{categories.map((category) => (
<FacetItem
active={values.includes(category)}
const allItemShown = limitedList.length + selectedBelowLimit.length === sortedItems.length;
return (
<>
- <FacetItemsList label={SecurityStandard.SONARSOURCE}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(SecurityStandard.SONARSOURCE)}>
{limitedList.map((item) => (
<FacetItem
active={values.includes(item)}
{selectedBelowLimit.length > 0 && (
<>
{!allItemShown && <div className="note spacer-bottom text-center">⋯</div>}
- <FacetItemsList label={SecurityStandard.SONARSOURCE}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(SecurityStandard.SONARSOURCE)}>
{selectedBelowLimit.map((item) => (
<FacetItem
active={true}
<FacetBox className="is-inner" property={SecurityStandard.SONARSOURCE}>
<FacetHeader
fetching={fetchingSonarSourceSecurity}
+ id={this.getFacetHeaderId(SecurityStandard.SONARSOURCE)}
name={translate('issues.facet.sonarsourceSecurity')}
onClick={this.handleSonarSourceSecurityHeaderClick}
open={sonarsourceSecurityOpen}
<FacetBox className="is-inner" property={SecurityStandard.OWASP_TOP10_2021}>
<FacetHeader
fetching={fetchingOwaspTop102021}
+ id={this.getFacetHeaderId(SecurityStandard.OWASP_TOP10_2021)}
name={translate('issues.facet.owaspTop10_2021')}
onClick={this.handleOwaspTop102021HeaderClick}
open={owaspTop102021Open}
<FacetBox className="is-inner" property={SecurityStandard.OWASP_TOP10}>
<FacetHeader
fetching={fetchingOwaspTop10}
+ id={this.getFacetHeaderId(SecurityStandard.OWASP_TOP10)}
name={translate('issues.facet.owaspTop10')}
onClick={this.handleOwaspTop10HeaderClick}
open={owaspTop10Open}
return (
<FacetBox property={this.property}>
<FacetHeader
+ id={this.getFacetHeaderId(this.property)}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
render() {
const { statuses, stats = {}, forceShow, fetching, open } = this.props;
const values = statuses.map((status) => translate('issue.status', status));
+ const headerId = `facet_${this.property}`;
if (values.length < 1 && !forceShow) {
return null;
<FacetBox property={this.property}>
<FacetHeader
fetching={fetching}
+ id={headerId}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
{open && (
<>
- <FacetItemsList label={this.property}>{STATUSES.map(this.renderItem)}</FacetItemsList>
+ <FacetItemsList labelledby={headerId}>{STATUSES.map(this.renderItem)}</FacetItemsList>
<MultipleSelectionHint options={Object.keys(stats).length} values={statuses.length} />
</>
)}
render() {
const { types, stats = {}, forceShow, open, fetching } = this.props;
const values = types.map((type) => translate('issue.type', type));
+ const typeFacetHeaderId = `facet_${this.property}`;
if (values.length < 1 && !forceShow) {
return null;
<FacetBox property={this.property}>
<FacetHeader
fetching={fetching}
+ id={typeFacetHeaderId}
name={translate('issues.facet', this.property)}
onClear={this.handleClear}
onClick={this.handleHeaderClick}
{open && (
<>
- <FacetItemsList label={this.property}>
+ <FacetItemsList labelledby={typeFacetHeaderId}>
{ISSUE_TYPES.filter((t) => t !== 'SECURITY_HOTSPOT').map(this.renderItem)}
</FacetItemsList>
<MultipleSelectionHint options={Object.keys(stats).length} values={types.length} />
showFiltersButton: (showMore = true) =>
byRole('button', { name: `issues.show_${showMore ? 'more' : 'less'}_filters` }),
- ruleFacetList: byRole('list', { name: 'rules' }),
- languageFacetList: byRole('list', { name: 'languages' }),
+ ruleFacetList: byRole('list', { name: 'issues.facet.rules' }),
+ languageFacetList: byRole('list', { name: 'issues.facet.languages' }),
ruleFacetSearch: byRole('searchbox', { name: 'search.search_for_rules' }),
+ inNewCodeFilter: byRole('checkbox', { name: 'issues.new_code' }),
};
export async function waitOnDataLoaded() {
*/
import classNames from 'classnames';
import * as React from 'react';
-import { Button, ButtonLink } from '../../components/controls/buttons';
import HelpTooltip from '../../components/controls/HelpTooltip';
+import { Button, ButtonLink } from '../../components/controls/buttons';
import OpenCloseIcon from '../../components/icons/OpenCloseIcon';
import DeferredSpinner from '../../components/ui/DeferredSpinner';
import { translate, translateWithParameters } from '../../helpers/l10n';
disabled?: boolean;
disabledHelper?: string;
name: string;
+ id: string;
onClear?: () => void;
onClick?: () => void;
open: boolean;
}
render() {
- const { disabled, values, disabledHelper, name, open, children, fetching } = this.props;
+ const { disabled, values, disabledHelper, name, open, children, fetching, id } = this.props;
const showClearButton = values != null && values.length > 0 && this.props.onClear != null;
const header = disabled ? (
<Tooltip overlay={disabledHelper}>
onClick={this.handleClick}
aria-expanded={open}
tabIndex={0}
+ id={id}
>
<OpenCloseIcon className="little-spacer-right" open={open} />
{header}
{this.renderHelper()}
</span>
) : (
- <span className="search-navigator-facet-header display-flex-center">
+ <span className="search-navigator-facet-header display-flex-center" id={id}>
{header}
{this.renderHelper()}
</span>
*/
import * as React from 'react';
-export interface FacetItemsListProps {
- children?: React.ReactNode;
- label: string;
-}
+export type FacetItemsListProps =
+ | {
+ children?: React.ReactNode;
+ labelledby: string;
+ label?: never;
+ }
+ | {
+ children?: React.ReactNode;
+ labelledby?: never;
+ label: string;
+ };
-export default function FacetItemsList({ children, label }: FacetItemsListProps) {
+export default function FacetItemsList({ children, labelledby, label }: FacetItemsListProps) {
+ const props = labelledby ? { 'aria-labelledby': labelledby } : { 'aria-label': label };
return (
- <div className="search-navigator-facet-list" role="list" aria-label={label}>
+ <div className="search-navigator-facet-list" role="list" {...props}>
{children}
</div>
);
return stats && stats[item] !== undefined ? stats && stats[item] : undefined;
}
+ getFacetHeaderId = (property: string) => {
+ return `facet_${property}`;
+ };
+
showFullList = () => {
this.setState({ showFullList: true });
};
return (
<>
- <FacetItemsList label={property}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(property)}>
{limitedList.map((item) => (
<FacetItem
active={this.props.values.includes(item)}
{selectedBelowLimit.length > 0 && (
<>
<div className="note spacer-bottom text-center">⋯</div>
- <FacetItemsList label={property}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(property)}>
{selectedBelowLimit.map((item) => (
<FacetItem
active={true}
return (
<>
- <FacetItemsList label={property}>
+ <FacetItemsList labelledby={this.getFacetHeaderId(property)}>
{searchResults.map((result) => this.renderSearchResult(result))}
</FacetItemsList>
{searchMaxResults && (
fetching={fetching}
name={facetHeader}
disabled={disabled}
+ id={this.getFacetHeaderId(property)}
disabledHelper={disabledHelper}
onClear={this.handleClear}
onClick={disabled ? undefined : this.handleHeaderClick}
import FacetBox, { FacetBoxProps } from '../FacetBox';
import FacetHeader from '../FacetHeader';
import FacetItem from '../FacetItem';
-import FacetItemsList, { FacetItemsListProps } from '../FacetItemsList';
+import FacetItemsList from '../FacetItemsList';
it('should render and function correctly', () => {
const onFacetClick = jest.fn();
- renderFacet(undefined, undefined, undefined, { onClick: onFacetClick });
+ renderFacet(undefined, undefined, { onClick: onFacetClick });
// Start closed.
let facetHeader = screen.getByRole('button', { name: 'foo', expanded: false });
function renderFacet(
facetBoxProps: Partial<FacetBoxProps> = {},
facetHeaderProps: Partial<FacetHeader['props']> = {},
- facetItemListProps: Partial<FacetItemsListProps> = {},
facetItemProps: Partial<FacetItem['props']> = {}
) {
function Facet() {
const [values, setValues] = React.useState(facetHeaderProps.values ?? undefined);
const property = 'foo';
+ const headerId = `facet_${property}`;
return (
<FacetBox property={property} {...facetBoxProps}>
<FacetHeader
+ id={headerId}
name="foo"
onClick={() => setOpen(!open)}
onClear={() => setValues(undefined)}
/>
{open && (
- <FacetItemsList label={property} {...facetItemListProps}>
+ <FacetItemsList labelledby={headerId}>
<FacetItem
active={true}
name="Foo/Bar"
disabled={true}
disabledHelper="Disabled helper description"
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
open={false}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
value=""
/>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={true}
⋯
</div>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={true}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
value=""
/>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={false}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
value="query"
/>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={false}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
value="query"
/>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={false}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
value=""
/>
<FacetItemsList
- label="foo"
+ labelledby="facet_foo"
>
<FacetItem
active={false}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}
>
<FacetHeader
fetching={false}
+ id="facet_foo"
name="facet header"
onClear={[Function]}
onClick={[Function]}