-
Notifications
You must be signed in to change notification settings - Fork 957
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,259 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* Creates array from `source` parameter if needed | ||
* | ||
* @param source (T | T[]) - any object which should be wrapped to an array | ||
* @returns (T[]) - wrapped `source` if was need to wrap, `source` otherwise | ||
*/ | ||
|
||
export function toArray<T>(source: T | T[]): T[] { | ||
if (Array.isArray(source)) { | ||
return source; | ||
} | ||
return [source]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { | ||
NativeSyntheticEvent, | ||
NativeScrollEvent, | ||
} from 'react-native'; | ||
|
||
export type ScrollEvent = NativeSyntheticEvent<NativeScrollEvent>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import React from 'react'; | ||
import { | ||
View, | ||
Image, | ||
Text, | ||
ViewProps, | ||
ImageProps, | ||
TextProps, | ||
ImageSourcePropType, | ||
} from 'react-native'; | ||
import { | ||
StyledComponentProps, | ||
StyleType, | ||
} from '@kitten/theme'; | ||
|
||
interface TabProps { | ||
title?: string; | ||
icon?: ImageSourcePropType; | ||
} | ||
|
||
export type Props = TabProps & StyledComponentProps & ViewProps; | ||
|
||
export class Tab extends React.Component<Props> { | ||
|
||
private getComponentStyle = (source: StyleType): StyleType => { | ||
return { | ||
container: { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}, | ||
icon: {}, | ||
title: {}, | ||
}; | ||
}; | ||
|
||
private createTextComponent = (style: StyleType): React.ReactElement<TextProps> => ( | ||
<Text | ||
style={style} | ||
key={1}> | ||
{this.props.title} | ||
</Text> | ||
); | ||
|
||
private createImageComponent = (style: StyleType): React.ReactElement<ImageProps> => ( | ||
<Image | ||
style={style} | ||
key={0} | ||
source={this.props.icon} | ||
/> | ||
); | ||
|
||
private createComponentChildren = (style: StyleType): React.ReactNode => { | ||
const { icon, title } = this.props; | ||
|
||
return [ | ||
icon ? this.createImageComponent(style.icon) : undefined, | ||
title ? this.createTextComponent(style.title) : undefined, | ||
]; | ||
}; | ||
|
||
public render(): React.ReactNode { | ||
const componentStyle: StyleType = this.getComponentStyle(this.props.themedStyle); | ||
const children = this.createComponentChildren(componentStyle); | ||
|
||
return ( | ||
<View | ||
{...this.props} | ||
style={[this.props.style, componentStyle.container]}> | ||
{children} | ||
</View> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { ThemeMappingType } from 'eva/packages/common'; | ||
import { ThemeType } from '@kitten/theme'; | ||
|
||
|
||
export const mapping: ThemeMappingType = { | ||
Tab: { | ||
meta: { | ||
variants: {}, | ||
states: [ | ||
'selected', | ||
'active', | ||
], | ||
}, | ||
appearance: { | ||
default: { | ||
mapping: { | ||
state: { | ||
selected: {}, | ||
active: {}, | ||
'selected.active': {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
TabBar: { | ||
meta: { | ||
variants: {}, | ||
states: [], | ||
}, | ||
appearance: { | ||
default: { | ||
mapping: { | ||
barSize: 42, | ||
indicatorSize: 4, | ||
indicatorBorderRadius: 2, | ||
indicatorColor: 'pink-primary', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export const theme: ThemeType = { | ||
'blue-primary': '#3366FF', | ||
'blue-dark': '#2541CC', | ||
'gray-light': '#DDE1EB', | ||
'gray-primary': '#A6AEBD', | ||
'gray-dark': '#8992A3', | ||
'gray-highlight': '#EDF0F5', | ||
'pink-primary': '#FF3D71', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import React from 'react'; | ||
import { | ||
View, | ||
ScrollView, | ||
} from 'react-native'; | ||
import { | ||
fireEvent, | ||
render, | ||
} from 'react-native-testing-library'; | ||
import { ReactTestInstance } from 'react-test-renderer'; | ||
import { | ||
styled, | ||
StyleProvider, | ||
StyleProviderProps, | ||
} from '@kitten/theme'; | ||
import { | ||
Tab as TabComponent, | ||
Props as TabProps, | ||
} from './tab.component'; | ||
import { | ||
TabBar as TabBarComponent, | ||
Props as TabBarProps, | ||
} from './tabBar.component'; | ||
import { | ||
TabView, | ||
Props as TabViewProps, | ||
ChildProps as TabViewChildProps, | ||
} from './tabView.component'; | ||
import * as config from './tab.spec.contig'; | ||
|
||
const Tab = styled<TabComponent, TabProps>(TabComponent); | ||
const TabBar = styled<TabBarComponent, TabBarProps>(TabBarComponent); | ||
|
||
describe('@tab: component checks', () => { | ||
|
||
const Mock = (props?: TabProps): React.ReactElement<StyleProviderProps> => ( | ||
<StyleProvider mapping={config.mapping} theme={config.theme} styles={{}}> | ||
<Tab {...props} /> | ||
</StyleProvider> | ||
); | ||
|
||
it('* empty', () => { | ||
const component = render( | ||
<Mock/>, | ||
); | ||
|
||
expect(component).toMatchSnapshot(); | ||
}); | ||
|
||
it('* title', () => { | ||
const component = render( | ||
<Mock | ||
title='title' | ||
/>, | ||
); | ||
|
||
expect(component).toMatchSnapshot(); | ||
}); | ||
|
||
it('* icon', () => { | ||
const component = render( | ||
<Mock | ||
icon={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png' }} | ||
/>, | ||
); | ||
|
||
expect(component).toMatchSnapshot(); | ||
}); | ||
|
||
}); | ||
|
||
describe('@tab-bar: component checks', () => { | ||
|
||
const childTestId0: string = '@tab-bar/child-0'; | ||
const childTestId1: string = '@tab-bar/child-1'; | ||
|
||
const Mock = (props?: TabBarProps): React.ReactElement<StyleProviderProps> => ( | ||
<StyleProvider mapping={config.mapping} theme={config.theme} styles={{}}> | ||
<TabBar {...props}>{props.children}</TabBar> | ||
</StyleProvider> | ||
); | ||
|
||
const ChildMock = Tab; | ||
|
||
it('* emits onSelect with correct args', () => { | ||
const onSelect = jest.fn(); | ||
|
||
const component = render( | ||
<Mock onSelect={onSelect}> | ||
<ChildMock testID={childTestId0}/> | ||
<ChildMock testID={childTestId1}/> | ||
</Mock>, | ||
); | ||
|
||
const child1 = component.getByTestId(childTestId1); | ||
|
||
fireEvent.press(child1); | ||
|
||
expect(onSelect).toBeCalledWith(1); | ||
}); | ||
|
||
}); | ||
|
||
describe('@tab-view: component checks', () => { | ||
|
||
const Mock = (props?: TabViewProps): React.ReactElement<TabViewProps> => ( | ||
<StyleProvider mapping={config.mapping} theme={config.theme} styles={{}}> | ||
<TabView {...props}>{props.children}</TabView> | ||
</StyleProvider> | ||
); | ||
|
||
const ChildMock = (props?: TabViewChildProps): React.ReactElement<TabViewChildProps> => ( | ||
<Tab {...props} /> | ||
); | ||
|
||
it('* emits onSelect with correct args', () => { | ||
const onSelect = jest.fn(); | ||
|
||
const component = render( | ||
<Mock contentWidth={375} onSelect={onSelect}> | ||
<ChildMock> | ||
<View/> | ||
</ChildMock> | ||
<ChildMock> | ||
<View/> | ||
</ChildMock> | ||
</Mock>, | ||
); | ||
|
||
const scrollView: ReactTestInstance = component.getByType(ScrollView); | ||
|
||
fireEvent(scrollView, 'momentumScrollEnd', { | ||
nativeEvent: { | ||
contentOffset: { | ||
x: 375, | ||
}, | ||
}, | ||
}); | ||
|
||
expect(onSelect).toBeCalledWith(1); | ||
}); | ||
|
||
it('* shouldLoadComponent disables child loading', () => { | ||
const disabledComponentIndex: number = 1; | ||
|
||
const shouldLoadComponent = jest.fn((...args: any[]) => { | ||
const index: number = args[0]; | ||
return index !== disabledComponentIndex; | ||
}); | ||
|
||
const component = render( | ||
<Mock contentWidth={375} shouldLoadComponent={shouldLoadComponent}> | ||
<ChildMock> | ||
<View/> | ||
</ChildMock> | ||
<ChildMock> | ||
<View/> | ||
</ChildMock> | ||
</Mock>, | ||
); | ||
|
||
const scrollView: ReactTestInstance = component.getByType(ScrollView); | ||
|
||
const unloadedChild = scrollView.props.children[disabledComponentIndex]; | ||
|
||
expect(unloadedChild.props.children).toEqual(undefined); | ||
}); | ||
|
||
}); | ||
|
Oops, something went wrong.