react-native-mmkv
Version:
⚡️ The fastest key/value storage for React Native.
99 lines (98 loc) • 3.76 kB
JavaScript
import React from 'react';
import { Button, Text } from 'react-native';
import { act, fireEvent, render, renderHook, screen, cleanup, waitFor, } from '@testing-library/react-native';
import { createMMKV, useMMKVNumber, useMMKVString } from '..';
const mmkv = createMMKV();
beforeEach(() => {
mmkv.clearAll();
mmkv.trim();
});
afterEach(() => {
cleanup();
});
test('hooks update when the value is changed directly through the instance', () => {
const { result } = renderHook(() => useMMKVString('string-key', mmkv));
expect(result.current[0]).toBeUndefined();
// First, make a "normal" change
act(() => {
result.current[1]('value 1');
});
expect(result.current[0]).toStrictEqual('value 1');
// Now, make the change directly through the instance.
act(() => {
mmkv.set('string-key', 'value 2');
});
expect(result.current[0]).toStrictEqual('value 2');
});
test('functional updates to hooks', () => {
const Component = () => {
const [state, setState] = React.useState(0);
const [value, setValue] = useMMKVNumber('number-key', mmkv);
return (React.createElement(React.Fragment, null,
React.createElement(Button, { testID: "button", title: "Double Increment Me", onPress: () => {
// Increment the state value twice, using the function form of useState.
setState((current) => current + 1);
setState((current) => current + 1);
// Increment the MMKV value twice, using the same function form.
setValue((current) => (current ?? 0) + 1);
setValue((current) => (current ?? 0) + 1);
} }),
React.createElement(Text, { testID: "state-value" },
"State: ",
state.toString()),
React.createElement(Text, { testID: "mmkv-value" },
"MMKV: ",
(value ?? 0).toString())));
};
render(React.createElement(Component, null));
const button = screen.getByTestId('button');
// Why these assertions:
// https://github.com/mrousavy/react-native-mmkv/issues/599
fireEvent.press(button);
expect(screen.getByTestId('state-value').children).toStrictEqual([
'State: ',
'2',
]);
expect(screen.getByTestId('mmkv-value').children).toStrictEqual([
'MMKV: ',
'2',
]);
fireEvent.press(button);
expect(screen.getByTestId('state-value').children).toStrictEqual([
'State: ',
'4',
]);
expect(screen.getByTestId('mmkv-value').children).toStrictEqual([
'MMKV: ',
'4',
]);
});
test('useMMKV hook does not miss updates that happen during subscription setup', async () => {
const raceKey = 'race-key';
const raceMMKV = createMMKV();
let simulatedRaceDone = false;
const originalSubscribe = raceMMKV.addOnValueChangedListener.bind(raceMMKV);
raceMMKV.addOnValueChangedListener = ((listener) => {
if (!simulatedRaceDone) {
simulatedRaceDone = true;
raceMMKV.set(raceKey, 'updated-before-subscribe');
}
return originalSubscribe(listener);
});
const { result } = renderHook(() => useMMKVString(raceKey, raceMMKV));
await waitFor(() => {
expect(result.current[0]).toBe('updated-before-subscribe');
});
});
test('useMMKV hook stays consistent during rapid updates', async () => {
const raceKey = 'rapid-key';
const { result } = renderHook(() => useMMKVNumber(raceKey, mmkv));
act(() => {
for (let i = 1; i <= 100; i++) {
mmkv.set(raceKey, i);
}
});
await waitFor(() => {
expect(result.current[0]).toBe(100);
});
});