Skip to content

Commit

Permalink
prepare support for disableable actionsheet items (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
vonovak authored Aug 16, 2020
1 parent 188c7ac commit 708613f
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 57 deletions.
94 changes: 45 additions & 49 deletions src/__tests__/overflowMenuPressHandlers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Divider } from '../overflowMenu/vendor/Divider';
describe('overflowMenuPressHandlers', () => {
describe('extractOverflowButtonData', () => {
it(
'extracts titles, onPresses and destructive flags when given an array of ' +
'extracts titles, onPresses and destructive+disabled flags when given an array of ' +
'HiddenItem or custom function components that render HiddenItem',
() => {
const prefix = 'customized_';
Expand All @@ -25,33 +25,50 @@ describe('overflowMenuPressHandlers', () => {

const propsArray = [
{ title: 'one', onPress: jest.fn() },
{ title: 'two', onPress: jest.fn() },
{ title: 'two', onPress: jest.fn(), disabled: true },
{ title: 'three', onPress: jest.fn(), destructive: true },
];
const items = [
const titlesAndOnPresses = extractOverflowButtonData([
...propsArray.map((props) => <HiddenItem {...props} />),
...propsArray.map((props) => <WrappedHiddenItem {...props} />),
];
const titlesAndOnPresses = extractOverflowButtonData(items);
]);

expect(titlesAndOnPresses).toStrictEqual([
{ title: propsArray[0].title, onPress: propsArray[0].onPress, destructive: undefined },
{ title: propsArray[1].title, onPress: propsArray[1].onPress, destructive: undefined },
{ title: propsArray[2].title, onPress: propsArray[2].onPress, destructive: true },
{
title: propsArray[0].title,
onPress: propsArray[0].onPress,
destructive: false,
disabled: false,
},
{
title: propsArray[1].title,
onPress: propsArray[1].onPress,
destructive: false,
disabled: true,
},
{
title: propsArray[2].title,
onPress: propsArray[2].onPress,
destructive: true,
disabled: false,
},
{
title: prefix + propsArray[0].title,
onPress: propsArray[0].onPress,
destructive: undefined,
destructive: false,
disabled: false,
},
{
title: prefix + propsArray[1].title,
onPress: propsArray[1].onPress,
destructive: undefined,
destructive: false,
disabled: true,
},
{
title: prefix + propsArray[2].title,
onPress: propsArray[2].onPress,
destructive: true,
disabled: false,
},
]);
}
Expand Down Expand Up @@ -99,20 +116,14 @@ describe('overflowMenuPressHandlers', () => {
});

describe('corner cases', () => {
const NestedHiddenItem = () => (
<HiddenItem title="disabled-nested" onPress={jest.fn()} disabled />
);
const NullNestedComponent = () => null;

it.each([
[null],
[undefined],
[[<HiddenItem title="disabled" onPress={jest.fn()} disabled />]],
[[<NestedHiddenItem />]],
[[<NullNestedComponent />]],
])('extractOverflowButtonData works for case %#', (input) => {
expect(extractOverflowButtonData(input)).toEqual([]);
});
it.each([[null], [undefined], [[<NullNestedComponent />]]])(
'extractOverflowButtonData works for case %#',
(input) => {
expect(extractOverflowButtonData(input)).toEqual([]);
}
);
});

it('ignores invalid / non-element values', () => {
Expand All @@ -122,13 +133,19 @@ describe('overflowMenuPressHandlers', () => {

it('works for single child element', () => {
const props = { title: 'one', onPress: jest.fn() };
expect(extractOverflowButtonData(<HiddenItem {...props} />)).toEqual([props]);
expect(extractOverflowButtonData(<HiddenItem {...props} />)).toEqual([
{ ...props, disabled: false, destructive: false },
]);
expect(extractOverflowButtonData(null)).toEqual([]);
});
});

describe('overflow button press handlers: given an array of {title, onPress}', () => {
const hiddenButtons = [{ title: 'one', onPress: jest.fn() }];
const hiddenButtons = [
{ title: 'one', onPress: jest.fn() },
{ title: 'two', onPress: jest.fn(), disabled: true },
{ title: 'three', onPress: jest.fn(), destructive: true },
];
beforeEach(() => {
ActionSheetIOS.showActionSheetWithOptions = jest.fn();
// $FlowExpectedError
Expand All @@ -145,30 +162,9 @@ describe('overflowMenuPressHandlers', () => {
expect(ActionSheetIOS.showActionSheetWithOptions).toHaveBeenCalledWith(
{
cancelButtonIndex: 0,
destructiveButtonIndex: [],
options: ['Cancel', 'one'],
},
expect.any(Function) // press callback
);
});

it('overflowMenuPressHandlerActionSheet should call ActionSheet with correct destructiveButtonIndex param', () => {
const hiddenButtonsWithDestructive = [
{ title: 'one', onPress: jest.fn() },
{ title: 'two', onPress: jest.fn(), destructive: true },
{ title: 'three', onPress: jest.fn(), destructive: true },
];
overflowMenuPressHandlerActionSheet({
hiddenButtons: hiddenButtonsWithDestructive,
overflowButtonRef: null,
children: null,
_private_toggleMenu: jest.fn(),
});
expect(ActionSheetIOS.showActionSheetWithOptions).toHaveBeenCalledWith(
{
cancelButtonIndex: 0,
destructiveButtonIndex: [2, 3],
options: ['Cancel', 'one', 'two', 'three'],
// disabledButtonsIndices: [1],
destructiveButtonIndex: [2],
options: ['Cancel', 'one', 'three'],
},
expect.any(Function) // press callback
);
Expand All @@ -183,7 +179,7 @@ describe('overflowMenuPressHandlers', () => {
});
expect(UIManager.showPopupMenu).toHaveBeenCalledWith(
null,
['one'],
['one', 'three'],
expect.any(Function), // error callback
expect.any(Function) // press callback
);
Expand Down
6 changes: 4 additions & 2 deletions src/overflowMenu/__tests__/OverflowMenu.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ describe('overflowMenu', () => {
fireEvent.press(getByA11yLabel('More options'));
expect(onPress).toHaveBeenCalledWith({
hiddenButtons: [
{ title: 'search', onPress: searchOnPress },
{ title: 'delete', onPress: deleteOnPress },
{ title: 'search', onPress: searchOnPress, destructive: false, disabled: false },
{ title: 'search2', onPress: searchOnPress, destructive: false, disabled: true },
{ title: 'delete', onPress: deleteOnPress, destructive: false, disabled: false },
],
overflowButtonRef: expect.any(Object),
children: expect.any(Array),
_private_toggleMenu: expect.any(Function),
});
expect(onPress).toHaveBeenCalled();
});

it('renders dropdown material menu correctly', () => {
Expand Down
15 changes: 9 additions & 6 deletions src/overflowMenuPressHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type OverflowButtonDescriptors = $ReadOnlyArray<{|
title: string,
onPress: () => void | Promise<void>,
destructive?: boolean,
disabled?: boolean,
|}>;

export const extractOverflowButtonData = (
Expand Down Expand Up @@ -53,7 +54,7 @@ const extract = (element: React.Element<any>) => {
const {
props: { title, onPress, disabled, destructive },
} = element;
return disabled === true ? false : { title, onPress, destructive };
return { title, onPress, destructive: destructive === true, disabled: disabled === true };
};

export type OnOverflowMenuPressParams = {|
Expand All @@ -73,14 +74,15 @@ export const overflowMenuPressHandlerActionSheet = ({
cancelButtonLabel = 'Cancel',
}: OnOverflowMenuPressParams) => {
checkParams(hiddenButtons);
let actionTitles = hiddenButtons.map((btn) => btn.title);
const destructiveActions: Array<number> = hiddenButtons.reduce((acc, btn, index) => {
const enabledButtons = hiddenButtons.filter((it) => it.disabled !== true);
let actionTitles = enabledButtons.map((btn) => btn.title);
actionTitles.unshift(cancelButtonLabel);
const destructiveActions: Array<number> = enabledButtons.reduce((acc, btn, index) => {
if (btn.destructive) {
acc.push(index + 1);
}
return acc;
}, []);
actionTitles.unshift(cancelButtonLabel);

ActionSheetIOS.showActionSheetWithOptions(
{
Expand All @@ -102,16 +104,17 @@ export const overflowMenuPressHandlerPopupMenu = ({
overflowButtonRef,
}: OnOverflowMenuPressParams) => {
checkParams(hiddenButtons);
const enabledButtons = hiddenButtons.filter((it) => it.disabled !== true);

UIManager.showPopupMenu(
findNodeHandle(overflowButtonRef),
hiddenButtons.map((btn) => btn.title),
enabledButtons.map((btn) => btn.title),
(err) => console.debug('overflowBtn error', err),
(eventName: string, index?: number) => {
if (eventName !== 'itemSelected' || typeof index !== 'number') {
return;
}
hiddenButtons[index].onPress();
enabledButtons[index].onPress();
}
);
};
Expand Down

0 comments on commit 708613f

Please sign in to comment.