import { mock } from "jest-mock-extended";

import { ForwarderContext } from "../engine";

import { ForwardEmail, ForwardEmailSettings } from "./forward-email";

describe("Addy.io forwarder", () => {
  const context = mock<ForwarderContext<ForwardEmailSettings>>();

  afterEach(() => {
    jest.resetAllMocks();
  });

  describe("authenticate", () => {
    it("returns a bearer header with the token", () => {
      context.authenticationToken.mockReturnValue("token");

      const result = ForwardEmail.authenticate(null, context);

      expect(result).toEqual({ Authorization: "Basic token" });
      expect(context.authenticationToken).toHaveBeenCalledWith({ base64: true, suffix: ":" });
    });
  });

  describe("settings", () => {
    it("should pass through deserialization", () => {
      const value: any = {};
      const result = ForwardEmail.forwarder.settings.deserializer(value);
      expect(result).toBe(value);
    });
  });

  describe("importBuffer", () => {
    it("should pass through deserialization", () => {
      const value: any = {};
      const result = ForwardEmail.forwarder.importBuffer.options.deserializer(value);
      expect(result).toBe(value);
    });
  });

  describe("createForwardingEmail", () => {
    describe("url", () => {
      it("returns the alias path", () => {
        context.baseUrl.mockReturnValue("");
        context.emailDomain.mockReturnValue("email domain");

        const result = ForwardEmail.forwarder.createForwardingEmail.url(null, context);

        expect(result).toEqual("/v1/domains/email domain/aliases");
      });
    });

    describe("body", () => {
      it("returns the alias path", () => {
        context.website.mockReturnValue("website");
        context.generatedBy.mockReturnValue("generated by");

        const result = ForwardEmail.forwarder.createForwardingEmail.body(null, context);

        expect(result).toEqual({
          labels: "website",
          description: "generated by",
        });
      });
    });

    describe("hasJsonPayload", () => {
      it.each([[200], [201]])("returns true when the status is $%i", (status) => {
        const result = ForwardEmail.forwarder.createForwardingEmail.hasJsonPayload(
          { status } as Response,
          context,
        );
        expect(result).toBeTruthy();
      });
    });

    describe("processJson", () => {
      it("should read the email from the response", () => {
        const json = { name: "foo", domain: { name: "example.com" } };

        const result = ForwardEmail.forwarder.createForwardingEmail.processJson(json, context);

        expect(result).toEqual(["foo@example.com"]);
      });

      it("should use the domain from the request when it is not specified", () => {
        context.emailDomain.mockReturnValue("example.com");
        const json = { name: "foo" };

        const result = ForwardEmail.forwarder.createForwardingEmail.processJson(json, context);

        expect(result).toEqual(["foo@example.com"]);
      });
    });
  });
});
