Skip to content

Commit

Permalink
Implement tests for initWithStoredValues and fix this logic in the hook
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioh8010 committed Mar 7, 2024
1 parent d74f7b5 commit 4927f38
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 7 deletions.
8 changes: 7 additions & 1 deletion lib/useOnyx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey

// Stores the previously result returned by the hook, containing the data from cache and the fetch status.
// We initialize it to `null` and `loading` fetch status to simulate the initial result when the hook is loading from the cache.
const resultRef = useRef<UseOnyxResult<TKey, TReturnValue>>([null as CachedValue<TKey, TReturnValue>, {status: 'loading'}]);
// However, if `initWithStoredValues` is `true` we set the fetch status to `loaded` since we want to signal that data is ready.
const resultRef = useRef<UseOnyxResult<TKey, TReturnValue>>([
null as CachedValue<TKey, TReturnValue>,
{
status: options?.initWithStoredValues === false ? 'loaded' : 'loading',
},
]);

// Indicates if it's the first Onyx connection of this hook or not, as we don't want certain use cases
// in `getSnapshot()` to be satisfied several times.
Expand Down
82 changes: 76 additions & 6 deletions tests/unit/useOnyxTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,14 @@ describe('useOnyx', () => {
});
});

describe('initial value', () => {
describe('initialValue', () => {
it('should return initial value from non-cached key and then return null', async () => {
// @ts-expect-error bypass
const {result} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initialValue: 'initial value'}));
const {result} = renderHook(() =>
useOnyx(ONYXKEYS.TEST_KEY, {
// @ts-expect-error bypass
initialValue: 'initial value',
}),
);

expect(result.current[0]).toEqual('initial value');
expect(result.current[1].status).toEqual('loaded');
Expand All @@ -238,8 +242,12 @@ describe('useOnyx', () => {
it('should return initial value from cached key and then return cached value', async () => {
await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test');

// @ts-expect-error bypass
const {result} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initialValue: 'initial value'}));
const {result} = renderHook(() =>
useOnyx(ONYXKEYS.TEST_KEY, {
// @ts-expect-error bypass
initialValue: 'initial value',
}),
);

expect(result.current[0]).toEqual('initial value');
expect(result.current[1].status).toEqual('loaded');
Expand All @@ -251,7 +259,7 @@ describe('useOnyx', () => {
});
});

describe('stale data', () => {
describe('allowStaleData', () => {
it('should return null and loading state while we have pending merges for the key, and then return updated value and loaded state', async () => {
Onyx.set(ONYXKEYS.TEST_KEY, 'test1');

Expand Down Expand Up @@ -288,4 +296,66 @@ describe('useOnyx', () => {
expect(result.current[1].status).toEqual('loaded');
});
});

describe('initWithStoredValues', () => {
it('should return null and loaded state, and after merge return updated value and loaded state', async () => {
await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1');

const {result} = renderHook(() => useOnyx(ONYXKEYS.TEST_KEY, {initWithStoredValues: false}));

await act(async () => waitForPromisesToResolve());

expect(result.current[0]).toEqual(null);
expect(result.current[1].status).toEqual('loaded');

await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test2'));

expect(result.current[0]).toEqual('test2');
expect(result.current[1].status).toEqual('loaded');
});

it('should return initial value and loaded state, and after merge return updated value and loaded state', async () => {
await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1');

const {result} = renderHook(() =>
useOnyx(ONYXKEYS.TEST_KEY, {
initWithStoredValues: false,
// @ts-expect-error bypass
initialValue: 'initial value',
}),
);

await act(async () => waitForPromisesToResolve());

expect(result.current[0]).toEqual('initial value');
expect(result.current[1].status).toEqual('loaded');

await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test2'));

expect(result.current[0]).toEqual('test2');
expect(result.current[1].status).toEqual('loaded');
});

it('should return selected value and loaded state, and after merge return updated selected value and loaded state', async () => {
await StorageMock.setItem(ONYXKEYS.TEST_KEY, 'test1');

const {result} = renderHook(() =>
useOnyx(ONYXKEYS.TEST_KEY, {
initWithStoredValues: false,
// @ts-expect-error bypass
selector: (value: OnyxEntry<string>) => `${value}_selected`,
}),
);

await act(async () => waitForPromisesToResolve());

expect(result.current[0]).toEqual('undefined_selected');
expect(result.current[1].status).toEqual('loaded');

await act(async () => Onyx.merge(ONYXKEYS.TEST_KEY, 'test2'));

expect(result.current[0]).toEqual('test2_selected');
expect(result.current[1].status).toEqual('loaded');
});
});
});

0 comments on commit 4927f38

Please sign in to comment.