import { defState, start, stop, isStarted } from ".";

const _inc41 = (): number => 41 + 1;
const _inc = (n: number): number => n + 1;

const obj = defState("obj", {
  start: async () => ({
    value: 42,
  }),
});

const mutableObj = defState("mutableObj", {
  start: async () => ({
    value: 41,
  }),
});

type FortyOneAdder = () => number;

type Incrementer = (n: number) => number;

const inc41 = defState<FortyOneAdder>("inc41", {
  isFunction: true,
  start: async () => _inc41,
});
const inc = defState<Incrementer>("inc", {
  isFunction: true,
  start: async () => _inc,
});

describe("defstate", () => {
  beforeEach(async () => {
    await start();
  });
  afterEach(async () => {
    await stop();
  });

  test("obj", async () => {
    expect(obj.value).toBe(42);
  });

  test("mutable obj", async () => {
    expect(mutableObj.value).toBe(41);
    mutableObj.value++;
    expect(mutableObj.value).toBe(42);
  });

  test("inc41", async () => {
    expect(inc41()).toBe(42);
    expect(isStarted("inc41")).toBe(true);
  });
  test("inc", async () => {
    expect(inc(41)).toBe(42);
  });
});

describe("errors", () => {
  test("doesn't exist", () => {
    expect(() => isStarted("not-real")).toThrow();
  });
  test("invalid type", () => {
    defState("invalid", { start: () => 42 as any });
    expect(start()).rejects.toThrow();
  });

  test("multiple defs", () => {
    defState("foo", { async start() {} });
    expect(() => {
      defState("foo", { async start() {} });
    }).toThrow();
  });
});
