import * as React from "react";
import generate from "./utils";
import {
    renderIntoDocument,
    render,
    cleanup,
    fireEvent,
    wait,
    Simulate,
} from "react-testing-library";
import TestComponent, {
    sumElements,
    DataItem,
} from "../components/TestComponent";
import { shallow } from "enzyme";

beforeEach(cleanup);

describe("Form tests", () => {
    test("01 - submit renders a div", async () => {
        // Arrange the test by setting up the action
        const pwchng = jest.fn();
        const component = (
            <TestComponent
                pwPress={pwchng}
                pwChange={pwchng}
                unChange={pwchng}
                data={[]}
            />
        );
        const { getByText, getByLabelText, getByTestId } = renderIntoDocument(
            component
        );
        const fakeUser = generate.genUsername();
        const fakePassword = generate.genPassword();
        (getByLabelText("Username") as any).value = fakeUser;
        (getByLabelText("Password") as any).value = fakePassword;

        // fire event triggers a dom event in this case clicking the submit button
        fireEvent.click(getByText("Submit"));

        // wait for async stuff to finish
        await wait(() => expect(getByTestId("submit-success")));

        const submitDiv = getByTestId("submit-success");
        expect(submitDiv).not.toBeNull();
        expect(submitDiv.textContent).not.toBeNull();
        expect(submitDiv.textContent).toBe("Success!");
    });
    test("02 - unit test for methods", () => {
        const nums = [1, 2, 3, 4, 5];
        expect(sumElements(nums)).toBe(15);
    });
    test("03 - automatic snapshot matching", () => {
        const pwchng = jest.fn();
        const component = (
            <TestComponent
                pwPress={pwchng}
                pwChange={pwchng}
                unChange={pwchng}
                data={[]}
            />
        );
        const { container } = render(component);

        expect(container).toMatchSnapshot();
    });
    test("04 - Events, note keypress not working :(", () => {
        const pwchng = jest.fn();
        const pwpress = jest.fn();
        const { getByLabelText } = renderIntoDocument(
            <TestComponent
                pwPress={pwpress}
                pwChange={pwchng}
                unChange={pwchng}
                data={[]}
            />
        );
        const password = getByLabelText("Password");
        fireEvent.focus(password);
        fireEvent.keyDown(password, {
            target: { key: "f" },
        });
        fireEvent.change(password, {
            target: { value: "fa" },
        });
        fireEvent.change(password, {
            target: { value: "fac" },
        });
        expect(pwchng).toHaveBeenCalledTimes(2);
        expect(pwpress).toHaveBeenCalledTimes(1);
    });
});

describe("enzyme tests for prop and state changes", () => {
    test("01 - state change", async () => {
        const pwchng = jest.fn();
        const unchng = jest.fn();
        const component = (
            <TestComponent
                pwPress={pwchng}
                pwChange={pwchng}
                unChange={unchng}
                data={[]}
            />
        );
        const wrapper = shallow(component);
        const data: DataItem[] = [
            { id: generate.genId(), name: generate.genName() },
            { id: generate.genId(), name: generate.genName() },
            { id: generate.genId(), name: generate.genName() },
        ];
        wrapper.setProps({ data });

        await wait(() => expect(wrapper.state("data").length).not.toBe(0));

        expect(wrapper.state().data).toEqual(data);
    });
});
