import AsyncStorage from '@react-native-community/async-storage';

import { load, loadString, save, saveString, clear, remove } from './storage';

// fixtures
const VALUE_OBJECT = { x: 1 };
const VALUE_STRING = JSON.stringify(VALUE_OBJECT);

describe('success branches', () => {
  beforeEach(() => {
    // @ts-ignore
    AsyncStorage.getItem.mockReturnValue(Promise.resolve(VALUE_STRING));
  });

  afterEach(() => jest.clearAllMocks());

  it('load', async () => {
    const value = await load('something');
    expect(value).toEqual(JSON.parse(VALUE_STRING));
  });

  it('loadString', async () => {
    const value = await loadString('something');
    expect(value).toEqual(VALUE_STRING);
  });

  it('save', async () => {
    const value = await save('something', VALUE_OBJECT);
    expect(AsyncStorage.setItem).toHaveBeenCalledWith('something', VALUE_STRING);
    expect(value).toBeTruthy();
  });

  it('saveString', async () => {
    const value = await saveString('something', VALUE_STRING);
    expect(AsyncStorage.setItem).toHaveBeenCalledWith('something', VALUE_STRING);
    expect(value).toBeTruthy();
  });

  it('remove', async () => {
    await remove('something');
    expect(AsyncStorage.removeItem).toHaveBeenCalledWith('something');
  });

  it('clear', async () => {
    await clear();
    expect(AsyncStorage.clear).toHaveBeenCalled();
  });
});

describe('exception branches', () => {
  beforeEach(() => {
    // @ts-ignore
    AsyncStorage.getItem.mockImplementation(() => {
      throw new Error();
    });
    // @ts-ignore
    AsyncStorage.setItem.mockImplementation(() => {
      throw new Error();
    });
  });

  afterEach(() => jest.clearAllMocks());

  it('load', async () => {
    const value = await load('something');
    expect(value).toBeNull();
  });

  it('loadString', async () => {
    const value = await loadString('something');
    expect(value).toBeNull();
  });

  it('save', async () => {
    const value = await save('something', VALUE_OBJECT);
    expect(AsyncStorage.setItem).toHaveBeenCalledWith('something', VALUE_STRING);
    expect(value).toBeFalsy();
  });

  it('saveString', async () => {
    const value = await saveString('something', VALUE_STRING);
    expect(AsyncStorage.setItem).toHaveBeenCalledWith('something', VALUE_STRING);
    expect(value).toBeFalsy();
  });
});
