Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/allow zero expanded #160

Merged
merged 5 commits into from Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions demo/js/demo.tsx
Expand Up @@ -67,9 +67,9 @@ const Example = (): JSX.Element => (
</AccordionItem>
</Accordion>

<h2 className="u-margin-top">Allow multiple</h2>
<h2 className="u-margin-top">Allow multiple/zero</h2>

<Accordion allowMultipleExpanded={true}>
<Accordion allowMultipleExpanded={true} allowZeroExpanded={true}>
<AccordionItem>
<AccordionItemHeading>
<h3 className="u-position-relative">
Expand Down Expand Up @@ -97,6 +97,15 @@ const Example = (): JSX.Element => (
AccordionItem
</td>
</tr>
<tr>
<td>allowZeroExpanded</td>
<td>Boolean</td>
<td>false</td>
<td>
Close an AccordionItem when it's the only
one expanded
</td>
</tr>
<tr>
<td>onChange</td>
<td>Function(keys)</td>
Expand Down
148 changes: 97 additions & 51 deletions src/Accordion/Accordion.spec.tsx
Expand Up @@ -23,7 +23,7 @@ describe('Accordion', () => {

function mountAccordion(): ReactWrapper {
return mount(
<Accordion allowMultipleExpanded={false}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice - that was redundant wasn't it

<Accordion>
<AccordionItem>
<FooTitle />
</AccordionItem>
Expand Down Expand Up @@ -62,21 +62,60 @@ describe('Accordion', () => {
).toEqual(1);
});

it('collapses an expanded item when its title is clicked', () => {
const wrapper = mountAccordion();

const fooTitle = wrapper.find(FooTitle);

fooTitle.simulate('click'); // open
fooTitle.simulate('click'); // close
it('pre expanded accordion', () => {
const wrapper = mount(
<Accordion>
<AccordionItem expanded={true}>Fake Child</AccordionItem>
<AccordionItem>Fake Child</AccordionItem>
</Accordion>,
);

const instance = wrapper.find(Provider).instance() as Provider;

expect(
instance.state.items.filter(
(item: Item) => item.expanded === true,
).length,
).toEqual(0);
).toEqual(1);
});

it('works with multiple pre expanded accordion. Extra expands are just ignored.', () => {
const hideBodyClassName = 'HIDE';
const wrapper = mount(
<Accordion allowMultipleExpanded={false}>
<AccordionItem
expanded={true}
hideBodyClassName={hideBodyClassName}
>
Fake Child
</AccordionItem>
<AccordionItem
expanded={true}
hideBodyClassName={hideBodyClassName}
>
Fake Child
</AccordionItem>
</Accordion>,
);

const instance = wrapper.find(Provider).instance() as Provider;

expect(
instance.state.items.filter((item: Item) => item.expanded)
.length,
).toEqual(1);
expect(
wrapper.findWhere((item: ReactWrapper) =>
item.hasClass(hideBodyClassName),
).length,
).toEqual(1);
});

it('respects arbitrary user-defined props', () => {
const wrapper = mount(<Accordion lang="en" />);
const div = wrapper.find('div').getDOMNode();

expect(div.getAttribute('lang')).toEqual('en');
});
});

Expand Down Expand Up @@ -128,10 +167,11 @@ describe('Accordion', () => {
).toEqual(2);
});

it('collapses an expanded item when its title is clicked', () => {
it('collapses an expanded item when its title is clicked and there is more than one item expanded', () => {
const wrapper = mountMultipleExpanded();

wrapper.find(FooTitle).simulate('click'); // open
wrapper.find(BarTitle).simulate('click'); // open
wrapper.find(FooTitle).simulate('click'); // close

const instance = wrapper.find(Provider).instance() as Provider;
Expand All @@ -140,7 +180,7 @@ describe('Accordion', () => {
instance.state.items.filter(
(item: Item) => item.expanded === true,
).length,
).toEqual(0);
).toEqual(1);
});
});

Expand All @@ -167,11 +207,11 @@ describe('Accordion', () => {
).toEqual(0);
});

it('pre expanded accordion', () => {
it('pre expanded accordion when allowMultipleExpanded is true', () => {
const wrapper = mount(
<Accordion>
<Accordion allowMultipleExpanded={true}>
<AccordionItem expanded={true}>Fake Child</AccordionItem>
<AccordionItem expanded={true}>Fake Child</AccordionItem>
<AccordionItem>Fake Child</AccordionItem>
</Accordion>,
);

Expand All @@ -180,60 +220,66 @@ describe('Accordion', () => {
expect(
instance.state.items.filter((item: Item) => item.expanded === true)
.length,
).toEqual(1);
).toEqual(2);
});
});

it('works with multiple pre expanded accordion. Extra expands are just ignored.', () => {
const hideBodyClassName = 'HIDE';
const wrapper = mount(
<Accordion allowMultipleExpanded={false}>
<AccordionItem
expanded={true}
hideBodyClassName={hideBodyClassName}
>
Fake Child
</AccordionItem>
<AccordionItem
expanded={true}
hideBodyClassName={hideBodyClassName}
>
Fake Child
describe('<Accordion allowZeroExpanded="false" />', () => {
const [FooTitle] = [
(): JSX.Element => <AccordionItemHeading>Foo</AccordionItemHeading>,
];

function mountAccordion(): ReactWrapper {
return mount(
<Accordion>
<AccordionItem>
<FooTitle />
</AccordionItem>
</Accordion>,
);
}

it("doesn't collapse an expanded item when it's the only item expanded", () => {
const wrapper = mountAccordion();

wrapper.find(FooTitle).simulate('click'); // open
wrapper.find(FooTitle).simulate('click'); // close

const instance = wrapper.find(Provider).instance() as Provider;

expect(
instance.state.items.filter((item: Item) => item.expanded).length,
).toEqual(1);
expect(
wrapper.findWhere((item: ReactWrapper) =>
item.hasClass(hideBodyClassName),
).length,
instance.state.items.filter((item: Item) => item.expanded === true)
.length,
).toEqual(1);
});
});

it('pre expanded accordion when allowMultipleExpanded is true', () => {
const wrapper = mount(
<Accordion allowMultipleExpanded={true}>
<AccordionItem expanded={true}>Fake Child</AccordionItem>
<AccordionItem expanded={true}>Fake Child</AccordionItem>
describe('<Accordion allowZeroExpanded="true" />', () => {
const [FooTitle] = [
(): JSX.Element => <AccordionItemHeading>Foo</AccordionItemHeading>,
];

function mountZeroExpanded(): ReactWrapper {
return mount(
<Accordion allowZeroExpanded={true}>
<AccordionItem>
<FooTitle />
</AccordionItem>
</Accordion>,
);
}

const instance = wrapper.find(Provider).instance() as Provider;
it("collapses an expanded item when its title is clicked and it's the only item open", () => {
const wrapper = mountZeroExpanded();

expect(
instance.state.items.filter((item: Item) => item.expanded === true)
.length,
).toEqual(2);
});
wrapper.find(FooTitle).simulate('click'); // open
wrapper.find(FooTitle).simulate('click'); // close

it('respects arbitrary user-defined props', () => {
const wrapper = mount(<Accordion lang="en" />);
const div = wrapper.find('div').getDOMNode();
const provider = wrapper.find(Provider).instance() as Provider;

expect(div.getAttribute('lang')).toEqual('en');
expect(
provider.state.items.filter((item: Item) => item.expanded === true)
.length,
).toEqual(0);
});
});
10 changes: 9 additions & 1 deletion src/Accordion/Accordion.wrapper.tsx
Expand Up @@ -15,6 +15,7 @@ type AccordionWrapperProps = Omit<
'onChange'
> & {
allowMultipleExpanded?: boolean;
allowZeroExpanded?: boolean;
onChange(args: UUID[]): void;
};

Expand All @@ -23,6 +24,7 @@ export default class AccordionWrapper extends React.Component<
> {
static defaultProps: AccordionWrapperProps = {
allowMultipleExpanded: false,
allowZeroExpanded: false,
onChange: (): void => {
//
},
Expand All @@ -31,7 +33,12 @@ export default class AccordionWrapper extends React.Component<
};

renderAccordion = (accordionStore: AccordionContainer): JSX.Element => {
const { allowMultipleExpanded, onChange, ...rest } = this.props;
const {
allowMultipleExpanded,
allowZeroExpanded,
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch. Would have caused console errors otherwise :)

onChange,
...rest
} = this.props;

return <Accordion {...rest} />;
};
Expand All @@ -40,6 +47,7 @@ export default class AccordionWrapper extends React.Component<
return (
<Provider
allowMultipleExpanded={this.props.allowMultipleExpanded}
allowZeroExpanded={this.props.allowZeroExpanded}
onChange={this.props.onChange}
>
<Consumer>{this.renderAccordion}</Consumer>
Expand Down