Skip to content

Commit

Permalink
Merge pull request #94 from instea/react-16.3
Browse files Browse the repository at this point in the history
React 16.3 upgrade
  • Loading branch information
sodik82 committed Apr 27, 2018
2 parents 2d522f6 + a2a4f59 commit 70c8197
Show file tree
Hide file tree
Showing 35 changed files with 4,283 additions and 481 deletions.
9 changes: 5 additions & 4 deletions __tests__/Menu-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ jest.mock('../src/helpers', () => ({
}));

jest.dontMock('../src/Menu');
const Menu = require('../src/Menu').default;
const exported = require('../src/Menu');
const { Menu, default: ExportedMenu } = exported;

const { objectContaining, createSpy, any } = jasmine;

Expand All @@ -36,8 +37,8 @@ describe('Menu', () => {
}

it('should export api', () => {
expect(typeof Menu.debug).toEqual('boolean');
expect(typeof Menu.setDefaultRenderer).toEqual('function');
expect(typeof ExportedMenu.debug).toEqual('boolean');
expect(typeof ExportedMenu.setDefaultRenderer).toEqual('function');
});

it('should render component and preserve children order', () => {
Expand Down Expand Up @@ -163,7 +164,7 @@ describe('Menu', () => {
<MenuOptions />
</Menu>
);
instance.componentDidUpdate();
instance.componentDidUpdate({});
expect(ctx.menuActions._notify).toHaveBeenCalled();
});

Expand Down
2 changes: 1 addition & 1 deletion __tests__/MenuOption-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { render, normalizeStyle, nthChild } from './helpers';

jest.dontMock('../src/MenuOption');
jest.dontMock('../src/helpers');
const MenuOption = require('../src/MenuOption').default;
const { MenuOption } = require('../src/MenuOption');
const { createSpy, objectContaining } = jasmine;

describe('MenuOption', () => {
Expand Down
8 changes: 5 additions & 3 deletions __tests__/MenuOptions-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { render } from './helpers';
import { MenuOption } from '../src/index';

jest.dontMock('../src/MenuOptions');
const MenuOptions = require('../src/MenuOptions').default;
const { MenuOptions } = require('../src/MenuOptions');

describe('MenuOptions', () => {

Expand Down Expand Up @@ -75,13 +75,15 @@ describe('MenuOptions', () => {
optionsWrapper: { backgroundColor: 'blue' },
};
const ctx = mockCtx();
const { instance } = render(
const { instance, renderer } = render(
<MenuOptions customStyles={customStyles} />,
ctx
);
instance.componentDidMount();
expect(ctx.menuRegistry.setOptionsCustomStyles)
.toHaveBeenLastCalledWith('menu1', customStyles)
instance.componentWillReceiveProps({ customStyles: customStyles2 })
renderer.render(<MenuOptions customStyles={customStyles2} ctx={ctx} />)
instance.componentDidUpdate();
expect(ctx.menuRegistry.setOptionsCustomStyles)
.toHaveBeenLastCalledWith('menu1', customStyles2)
});
Expand Down
36 changes: 23 additions & 13 deletions __tests__/MenuProvider-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { View, Text } from 'react-native';
import { render, waitFor, mockReactInstance } from './helpers';
import { render, waitFor, mockReactInstance, nthChild } from './helpers';
import { MenuOptions, MenuTrigger } from '../src/index';
import MenuOutside from '../src/renderers/MenuOutside';
import Backdrop from '../src/Backdrop';
Expand All @@ -25,7 +25,7 @@ jest.mock('../src/helpers', () => ({
iterator2array: it => [...it],
}));

const MenuProvider = require('../src/MenuProvider').default;
const {default: MenuProvider, PopupMenuContext} = require('../src/MenuProvider');

describe('MenuProvider', () => {

Expand Down Expand Up @@ -69,9 +69,14 @@ describe('MenuProvider', () => {
const rendered = render(
<MenuProvider {...props}/>
);
const { instance } = rendered;
const { instance, output } = rendered;
rendered.placeholder = mockReactInstance();
instance._onPlaceholderRef(rendered.placeholder);
// for tests mimic old ctx api
const ctx = output.props.value
instance.getChildContext = () => ctx
// and "strip" context provider
rendered.output = nthChild(output, 1)
return rendered;
}

Expand All @@ -92,24 +97,29 @@ describe('MenuProvider', () => {
expect(typeof instance.closeMenu).toEqual('function');
expect(typeof instance.toggleMenu).toEqual('function');
expect(typeof instance.isMenuOpen).toEqual('function');
const { menuRegistry, menuActions } = instance.getChildContext();
expect(typeof menuRegistry).toEqual('object');
expect(typeof menuActions).toEqual('object');
expect(typeof menuActions.openMenu).toEqual('function');
expect(typeof menuActions.closeMenu).toEqual('function');
expect(typeof menuActions.toggleMenu).toEqual('function');
expect(typeof menuActions.isMenuOpen).toEqual('function');
// plus internal methods
expect(typeof menuActions._notify).toEqual('function');
// context is now "renderer" -> see 'should render child components'
});

it('should render child components', () => {
const { output } = render(
let { output } = render(
<MenuProvider>
<View />
<Text>Some text</Text>
</MenuProvider>
);
// check context
expect(output.type).toEqual(PopupMenuContext.Provider);
const { menuRegistry, menuActions }=output.props.value;
expect(typeof menuRegistry).toEqual('object');
expect(typeof menuActions).toEqual('object');
expect(typeof menuActions.openMenu).toEqual('function');
expect(typeof menuActions.closeMenu).toEqual('function');
expect(typeof menuActions.toggleMenu).toEqual('function');
expect(typeof menuActions.isMenuOpen).toEqual('function');
// plus internal methods
expect(typeof menuActions._notify).toEqual('function');
// check the rest
output = nthChild(output, 1)
expect(output.type).toEqual(View);
expect(typeof output.props.onLayout).toEqual('function');
expect(output.props.children.length).toEqual(2);
Expand Down
11 changes: 5 additions & 6 deletions __tests__/MenuTrigger-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { render, normalizeStyle, nthChild } from './helpers';

jest.dontMock('../src/MenuTrigger');
jest.dontMock('../src/helpers');
const MenuTrigger = require('../src/MenuTrigger').default;
const { MenuTrigger } = require('../src/MenuTrigger');
const { createSpy, objectContaining } = jasmine;

describe('MenuTrigger', () => {
Expand Down Expand Up @@ -53,11 +53,10 @@ describe('MenuTrigger', () => {
});

it('should open menu', () => {
const { output, instance } = render(
<MenuTrigger menuName='menu1' />
);
const menuActions = { openMenu: createSpy() };
instance.context = { menuActions };
const { output } = render(
<MenuTrigger menuName='menu1' ctx={{menuActions}} />
);
nthChild(output, 1).props.onPress();
expect(menuActions.openMenu).toHaveBeenCalledWith('menu1');
expect(menuActions.openMenu.calls.count()).toEqual(1);
Expand All @@ -68,7 +67,7 @@ describe('MenuTrigger', () => {
<MenuTrigger menuName='menu1' disabled={true} />
);
const menuActions = { openMenu: createSpy() };
instance.context = { menuActions };
instance.props.ctx = { menuActions };
nthChild(output, 1).props.onPress();
expect(menuActions.openMenu).not.toHaveBeenCalled();
});
Expand Down
10 changes: 7 additions & 3 deletions __tests__/helpers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import React from 'react'
import ShallowRenderer from 'react-test-renderer/shallow';

/**
* Renders component and returns instance object and rendered output.
*/
export function render(Component, ctx) {
export function render(element, ctx) {
const renderer = new ShallowRenderer();
renderer.render(Component, ctx);
const instance = renderer._instance._instance;
if (ctx) {
element = React.cloneElement(element, { ctx })
}
renderer.render(element);
const instance = renderer.getMountedInstance();
const output = renderer.getRenderOutput();
return { output, instance, renderer };
}
Expand Down
2 changes: 1 addition & 1 deletion doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## MenuProvider

It provides methods to handle popup menus imperatively. The same methods are exposed to the child context with name `menuActions`.
It provides methods to handle popup menus imperatively. The same methods are exposed to the context property `menuActions`. This can be retrieved by HOC `withMenuContext` that adds `ctx` property to your component. Then simply call `props.ctx.menuActions.method()`.

**Note:** It is important that `<MenuProvider />` is on the top of the component hierarchy (e.g. `ScrollView` should be inside of `MenuProvider`) and wraps all `<Menu />` components.
This is needed in order to solve z-index issues.
Expand Down
27 changes: 18 additions & 9 deletions examples/.flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js

; Ignore polyfills
.*/Libraries/polyfills/.*

; Ignore metro
.*/node_modules/metro/.*

[include]

[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
node_modules/react-native/flow/
node_modules/react-native/flow-github/

[options]
emoji=true
Expand All @@ -30,16 +35,20 @@ munge_underscores=true

module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'

module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.json
module.file_ext=.native.js

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState

suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

unsafe.enable_getters_and_setters=true

[version]
^0.49.1
^0.67.0
11 changes: 7 additions & 4 deletions examples/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ buck-out/
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
# https://docs.fastlane.tools/best-practices/source-control/

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots

# Bundle artifact
*.jsbundle
4 changes: 3 additions & 1 deletion examples/ControlledExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ export default class ControlledExample extends Component {
}

render() {
const { opened } = this.state;
console.log('ControlledExample - opened', opened)
return (
<MenuProvider
style={{flexDirection: 'column', padding: 30}}>
<Text>Hello world!</Text>
<Menu
opened={this.state.opened}
opened={opened}
onBackdropPress={() => this.onBackdropPress()}
onSelect={value => this.onOptionSelect(value)}>
<MenuTrigger
Expand Down
7 changes: 3 additions & 4 deletions examples/Demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import Menu from 'react-native-popup-menu';

import Example from './Example';
import BasicExample from './BasicExample';
import OriginalExample from './OriginalExample';
import ControlledExample from './ControlledExample';
import ExtensionExample from './ExtensionExample';
import ModalExample from './ModalExample';
import StylingExample from './StylingExample';
import NonRootExample from './NonRootExample';
import NavigatorExample from './NavigatorExample';
// import NavigatorExample from './NavigatorExample';
import TouchableExample from './TouchableExample';
import MenuMethodsExample from './MenuMethodsExample';
import CloseOnBackExample from './CloseOnBackExample';
Expand All @@ -20,15 +19,15 @@ import PopoverExample from './PopoverExample';
const demos = [
{ Component: BasicExample, name: 'Basic example' },
{ Component: Example, name: 'Advanced example' },
{ Component: OriginalExample, name: 'Original example' },
{ Component: ControlledExample, name: 'Controlled example' },
{ Component: MenuMethodsExample, name: 'Controlling menu using menu methods' },
{ Component: ExtensionExample, name: 'Extensions example' },
{ Component: ModalExample, name: 'Modal example' },
{ Component: StylingExample, name: 'Styling example' },
{ Component: TouchableExample, name: 'Touchable config example' },
{ Component: NonRootExample, name: 'Non root example' },
{ Component: NavigatorExample, name: 'Example with react-native-router-flux' },
// FIXME demo is not working now
// { Component: NavigatorExample, name: 'Example with react-native-router-flux' },
{ Component: CloseOnBackExample, name: 'Close on back button press example' },
{ Component: FlatListExample, name: 'Using FlatList' },
{ Component: PopoverExample, name: 'Popover renderer' },
Expand Down
16 changes: 14 additions & 2 deletions examples/MenuMethodsExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ import Menu, {
MenuProvider,
MenuOptions,
MenuOption,
MenuTrigger
MenuTrigger,
withMenuContext,
} from 'react-native-popup-menu';

const Openner = (props) => (
<TouchableOpacity style={{ paddingTop: 50 }}
onPress={() => props.ctx.menuActions.openMenu('menu-1')}>
<Text>Open menu from context</Text>
</TouchableOpacity>
);

const ContextOpenner = withMenuContext(Openner);

export default class ControlledExample extends Component {

onOptionSelect(value) {
Expand All @@ -28,7 +38,8 @@ export default class ControlledExample extends Component {
render() {
return (
<MenuProvider style={{flexDirection: 'column', padding: 30}}>
<Menu onSelect={value => this.onOptionSelect(value)} ref={this.onRef}>
<Menu onSelect={value => this.onOptionSelect(value)}
name="menu-1" ref={this.onRef}>
<MenuTrigger text='Select option'/>
<MenuOptions>
<MenuOption value={1} text='One' />
Expand All @@ -38,6 +49,7 @@ export default class ControlledExample extends Component {
<TouchableOpacity style={{ paddingTop: 50 }} onPress={() => this.openMenu()}>
<Text>Open menu from outside</Text>
</TouchableOpacity>
<ContextOpenner />
</MenuProvider>
);
}
Expand Down

0 comments on commit 70c8197

Please sign in to comment.