import React from "react";
import { shallow } from "enzyme";
import JoinForm from "../components/screens/Lobby/JoinForm";

jest.mock("../domain/gameStore");

import { usePlayerName, dispatch } from "../domain/gameStore";

describe("JoinForm", () => {
  it("renders", () => {
    const onJoined = jest.fn();
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
  });

  it("blocks joining with empty player name", () => {
    const onJoined = jest.fn();
    usePlayerName.mockReturnValue("");
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
  });

  it("sets player name", () => {
    const onJoined = jest.fn();
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    rendered
      .find("input")
      .first()
      .simulate("change", { target: { value: "test" } });
    expect(dispatch.setPlayerName).toHaveBeenCalledWith("test");
  });

  it("joins game", async () => {
    const onJoined = jest.fn();
    usePlayerName.mockReturnValue("test-player");
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
    await rendered.find("button").first().simulate("click");
    expect(rendered).toMatchSnapshot();
    expect(dispatch.joinGame).toHaveBeenCalled();
    expect(onJoined).toHaveBeenCalled();
  });

  it("joins game if enter pressed in input", async () => {
    const onJoined = jest.fn();
    usePlayerName.mockReturnValue("test-player");
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
    await rendered.find("input").first().simulate("keydown", { key: "Enter" });
    expect(rendered).toMatchSnapshot();
    expect(dispatch.joinGame).toHaveBeenCalled();
    expect(onJoined).toHaveBeenCalled();
  });

  it("does not join game if other keys pressed in input", async () => {
    const onJoined = jest.fn();
    usePlayerName.mockReturnValue("test-player");
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
    await rendered.find("input").first().simulate("keydown", { key: "Escape" });
    expect(rendered).toMatchSnapshot();
    expect(dispatch.joinGame).not.toHaveBeenCalled();
    expect(onJoined).not.toHaveBeenCalled();
  });

  it("handles failure", async () => {
    dispatch.joinGame.mockImplementation(() => {
      throw new Error();
    });
    const onJoined = jest.fn();
    usePlayerName.mockReturnValue("test-player");
    const rendered = shallow(<JoinForm onJoined={onJoined} />);
    expect(rendered).toMatchSnapshot();
    await rendered.find("button").first().simulate("click");
    expect(rendered).toMatchSnapshot();
    expect(dispatch.joinGame).toHaveBeenCalled();
    expect(onJoined).not.toHaveBeenCalled();
  });
});
