Skip to content

feat: jest integration #102

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

Merged
merged 15 commits into from
Dec 16, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/verify-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ jobs:
node-version: 16.x
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run tests
run: yarn test
run: |
yarn install --frozen-lockfile
cd example
yarn install --frozen-lockfile
- name: Run lib tests
run: yarn test src
- name: Run example app tests (verify mocks)
run: |
cd example
yarn test
67 changes: 67 additions & 0 deletions docs/docs/recipes/jest-testing-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
sidebar_position: 3
---

# Jest testing guide

## Setting up a mock

This library includes a built in mock for Jest. To use it, add the following code to the [jest setup](https://jestjs.io/docs/configuration#setupfiles-array) file:

```js
jest.mock('react-native-keyboard-controller', () =>
require('react-native-keyboard-controller/jest')
);
```

## Test case example

Once you've set up mock - you can write your first test 😊. A sample of test case is shown below. For more test cases please see [this](https://github.com/kirillzyusko/react-native-keyboard-controller/tree/main/example/__tests__) link.

```tsx
import '@testing-library/jest-native/extend-expect';
import React from 'react';
import { Animated } from 'react-native';
import { render } from '@testing-library/react-native';

import { useKeyboardAnimation } from 'react-native-keyboard-controller';

function TestComponent() {
const { height } = useKeyboardAnimation();

return (
<Animated.View
testID="view"
style={{ transform: [{ translateY: height }] }}
/>
);
}

describe('basic keyboard interaction', () => {
it('should have different styles depends on position', () => {
const { getByTestId, update } = render(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({ transform: [{ translateY: 0 }] });

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(150),
progress: new Animated.Value(0.5),
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 150 }],
});

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(300),
progress: new Animated.Value(1),
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 300 }],
});
});
});
```
67 changes: 67 additions & 0 deletions docs/versioned_docs/version-1.4.0/recipes/jest-testing-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
sidebar_position: 3
---

# Jest testing guide

## Setting up a mock

This library includes a built in mock for Jest. To use it, add the following code to the [jest setup](https://jestjs.io/docs/configuration#setupfiles-array) file:

```js
jest.mock('react-native-keyboard-controller', () =>
require('react-native-keyboard-controller/jest')
);
```

## Test case example

Once you've set up mock - you can write your first test 😊. A sample of test case is shown below. For more test cases please see [this](https://github.com/kirillzyusko/react-native-keyboard-controller/tree/main/example/__tests__) link.

```tsx
import '@testing-library/jest-native/extend-expect';
import React from 'react';
import { Animated } from 'react-native';
import { render } from '@testing-library/react-native';

import { useKeyboardAnimation } from 'react-native-keyboard-controller';

function TestComponent() {
const { height } = useKeyboardAnimation();

return (
<Animated.View
testID="view"
style={{ transform: [{ translateY: height }] }}
/>
);
}

describe('basic keyboard interaction', () => {
it('should have different styles depends on position', () => {
const { getByTestId, update } = render(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({ transform: [{ translateY: 0 }] });

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(150),
progress: new Animated.Value(0.5),
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 150 }],
});

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(300),
progress: new Animated.Value(1),
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 300 }],
});
});
});
```
23 changes: 23 additions & 0 deletions example/__tests__/__snapshots__/components-rendering.spec.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`components rendering should render \`KeyboardControllerView\` 1`] = `
<KeyboardControllerView
statusBarTranslucent={true}
/>
`;

exports[`components rendering should render \`KeyboardProvider\` 1`] = `
<KeyboardProvider
statusBarTranslucent={true}
>
<View
style={
Object {
"backgroundColor": "black",
"height": 20,
"width": 20,
}
}
/>
</KeyboardProvider>
`;
45 changes: 45 additions & 0 deletions example/__tests__/basic-interaction.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import '@testing-library/jest-native/extend-expect';
import React from 'react';
import { Animated } from 'react-native';
import { render } from '@testing-library/react-native';

import { useKeyboardAnimation } from 'react-native-keyboard-controller';

function TestComponent() {
const { height } = useKeyboardAnimation();

return (
<Animated.View
testID="view"
style={{ transform: [{ translateY: height }] }}
/>
);
}

describe('basic keyboard interaction', () => {
it('should have different styles depends on position', () => {
const { getByTestId, update } = render(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({ transform: [{ translateY: 0 }] });

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(150),
progress: new Animated.Value(0.5),
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 150 }],
});

(useKeyboardAnimation as jest.Mock).mockReturnValue({
height: new Animated.Value(300),
progress: new Animated.Value(1),
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe it's better to split these object to fisrtPosition, secondPosition, thirdPosition?

const thirdPosition = {
      height: new Animated.Value(300),
      progress: new Animated.Value(1),
      };
      
 (useKeyboardAnimation as jest.Mock).mockReturnValue(thirdPosition);

});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 300 }],
});
});
});
29 changes: 29 additions & 0 deletions example/__tests__/components-rendering.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { View } from 'react-native';
import {
KeyboardControllerView,
KeyboardProvider,
} from 'react-native-keyboard-controller';
import { render } from '@testing-library/react-native';

function KeyboardControllerViewTest() {
return <KeyboardControllerView statusBarTranslucent />;
}

function KeyboardProviderTest() {
return (
<KeyboardProvider statusBarTranslucent>
<View style={{ width: 20, height: 20, backgroundColor: 'black' }} />
</KeyboardProvider>
);
}

describe('components rendering', () => {
it('should render `KeyboardControllerView`', () => {
expect(render(<KeyboardControllerViewTest />)).toMatchSnapshot();
});

it('should render `KeyboardProvider`', () => {
expect(render(<KeyboardProviderTest />)).toMatchSnapshot();
});
});
88 changes: 88 additions & 0 deletions example/__tests__/keyboard-handler.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
jest.unmock('react-native-reanimated');
jest.useFakeTimers();

global.ReanimatedDataMock = {
now: () => 0,
};

import '@testing-library/jest-native/extend-expect';
import React from 'react';
import Reanimated, {
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated';
import { render } from '@testing-library/react-native';

import {
KeyboardHandler,
NativeEvent,
useKeyboardHandler,
} from 'react-native-keyboard-controller';

function TestComponent() {
const height = useSharedValue(0);
useKeyboardHandler(
{
onStart: (e) => {
'worklet';
height.value = e.height;
},
onMove: (e) => {
'worklet';
height.value = e.height;
},
onEnd: (e) => {
'worklet';
height.value = e.height;
},
},
[]
);
const style = useAnimatedStyle(
() => ({
width: 20,
height: 20,
backgroundColor: 'red',
transform: [{ translateY: height.value }],
}),
[]
);

return <Reanimated.View testID="view" style={style} />;
}

describe('keyboard handler specification', () => {
it('should execute all handlers and change corresponding style properties', () => {
let handlers: KeyboardHandler = {};
(useKeyboardHandler as jest.Mock).mockImplementation(
(handler) => (handlers = handler)
);
const onStart = (e: NativeEvent) => handlers.onStart?.(e);
const onMove = (e: NativeEvent) => handlers.onMove?.(e);
const onEnd = (e: NativeEvent) => handlers.onEnd?.(e);
const { getByTestId } = render(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({ transform: [{ translateY: 0 }] });

onStart({ height: 100, progress: 1 });
jest.advanceTimersByTime(100);

expect(getByTestId('view')).toHaveAnimatedStyle({
transform: [{ translateY: 100 }],
});

onMove({ height: 20, progress: 0.2 });
jest.advanceTimersByTime(100);

expect(getByTestId('view')).toHaveAnimatedStyle({
transform: [{ translateY: 20 }],
});

onEnd({ height: 100, progress: 1 });
jest.advanceTimersByTime(100);

expect(getByTestId('view')).toHaveAnimatedStyle({
transform: [{ translateY: 100 }],
});
});
});
49 changes: 49 additions & 0 deletions example/__tests__/reanimated.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import '@testing-library/jest-native/extend-expect';
import React from 'react';
import Reanimated, { useAnimatedStyle } from 'react-native-reanimated';
import { render } from '@testing-library/react-native';

import { useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller';

function TestComponent() {
const { height } = useReanimatedKeyboardAnimation();
const style = useAnimatedStyle(
() => ({
width: 20,
height: 20,
backgroundColor: 'red',
transform: [{ translateY: height.value }],
}),
[]
);

return <Reanimated.View testID="view" style={style} />;
}

describe('basic keyboard interaction', () => {
it('should have different styles depends on position', () => {
const { getByTestId, update } = render(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({ transform: [{ translateY: 0 }] });

(useReanimatedKeyboardAnimation as jest.Mock).mockReturnValue({
height: { value: 150 },
progress: { progress: 0.5 },
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 150 }],
});

(useReanimatedKeyboardAnimation as jest.Mock).mockReturnValue({
height: { value: 300 },
progress: { progress: 1 },
});
update(<TestComponent />);

expect(getByTestId('view')).toHaveStyle({
transform: [{ translateY: 300 }],
});
});
});
Loading