import { of, throwError } from 'rxjs';
import { describe, expect, it, vi } from 'vitest';

import { useMutation } from './use-mutation';

describe('useMutation', () => {
  it('stores the resolved value and clears loading after a successful execution', async () => {
    const mutation = useMutation<{ id: number }, { ok: boolean; id: number }>();
    const factory = vi.fn((payload: { id: number }) => of({ ok: true, id: payload.id }));

    await expect(mutation.execute(factory, { id: 7 })).resolves.toEqual({ ok: true, id: 7 });

    expect(factory).toHaveBeenCalledWith({ id: 7 });
    expect(mutation.loading()).toBe(false);
    expect(mutation.error()).toBeNull();
    expect(mutation.data()).toEqual({ ok: true, id: 7 });
  });

  it('stores the thrown error and clears loading after a failed execution', async () => {
    const mutation = useMutation<{ id: number }, { ok: boolean }>();
    const failure = new Error('request failed');
    const factory = vi.fn(() => throwError(() => failure));

    await expect(mutation.execute(factory, { id: 7 })).rejects.toThrow('request failed');

    expect(factory).toHaveBeenCalledWith({ id: 7 });
    expect(mutation.loading()).toBe(false);
    expect(mutation.error()).toBe(failure);
    expect(mutation.data()).toBeNull();
  });
});
