teamdigitale/italia-app

View on GitHub
ts/utils/__tests__/payment.test.ts

Summary

Maintainability
D
2 days
Test Coverage
import { AmountInEuroCents, RptId } from "@pagopa/io-pagopa-commons/lib/pagopa";
import * as O from "fp-ts/lib/Option";
import { Tuple2 } from "@pagopa/ts-commons/lib/tuples";
import { pipe } from "fp-ts/lib/function";
import { PaymentAmount } from "../../../definitions/backend/PaymentAmount";
import I18n from "../../i18n";
import { Transaction } from "../../types/pagopa";
import {
  cleanTransactionDescription,
  decodePagoPaQrCode,
  decodePosteDataMatrix,
  DetailV2Keys,
  ErrorTypes,
  getAmountFromPaymentAmount,
  getCodiceAvviso,
  getErrorDescriptionV2,
  getTransactionFee,
  getTransactionIUV,
  getV2ErrorMainType
} from "../payment";

describe("getAmountFromPaymentAmount", () => {
  const aPaymentAmount = 1 as PaymentAmount;
  it("should convert a valid PaymentAmount into an AmountInEuroCents", () => {
    const amountInEuroCents = pipe(
      getAmountFromPaymentAmount(aPaymentAmount),
      O.getOrElse(() => "💰" as AmountInEuroCents)
    );
    expect(amountInEuroCents).toEqual("01" as AmountInEuroCents);
  });
});

describe("cleanTransactionDescription", () => {
  it("should remove the tag returning just the description", () => {
    [
      [
        "/RFB/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "RFB/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "/RFA/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "RFA/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "RFS/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "/RFS/0123456789012/666.98/TXT/ actual description",
        "actual description"
      ],
      [
        "/RFS/0123456789012/666.98/TXT/ actual description/other text",
        "actual description/other text"
      ],
      [
        "/RFB/000001234556859/143.00",
        `${I18n.t("payment.IUV")} 000001234556859`
      ],
      ["/XYZ/TXT/some text", "some text"],
      ["/TXT/some text", "some text"],
      ["TXT/some text", "some text"],
      ["/TXT/some text/other text", "some text/other text"],
      ["TXT/some text/other text", "some text/other text"],
      ["actual description", "actual description"]
    ].forEach(([dirty, cleaned]) => {
      expect(cleanTransactionDescription(dirty)).toEqual(cleaned);
    });
  });
});

describe("decodePagoPaQrCode", () => {
  it("should decode a string encoded into a pagoPa QRcode", () => {
    [
      Tuple2(
        "PAGOPA|002|322201151398574181|81005750021|01",
        O.some(
          Tuple2(
            {
              organizationFiscalCode: "81005750021",
              paymentNoticeNumber: {
                auxDigit: "3",
                checkDigit: "81",
                iuv13: "2011513985741",
                segregationCode: "22"
              }
            },
            "01"
          )
        )
      ),
      // not supported version
      Tuple2("PAGOPA|003|322201151398574181|810057500211|01A", O.none),
      // invalid amount
      Tuple2("PAGOPA|002|322201151398574181|810057500211|01A", O.none),
      // invalid header
      Tuple2("PAPAGO|002|322201151398574181|810057500211|01", O.none),
      // this is valid
      Tuple2(
        "PAGOPA|002|322201151398574181|81005750021|1",
        O.some(
          Tuple2(
            {
              organizationFiscalCode: "81005750021",
              paymentNoticeNumber: {
                auxDigit: "3",
                checkDigit: "81",
                iuv13: "2011513985741",
                segregationCode: "22"
              }
            },
            "1"
          )
        )
      ),
      // invalid organization fiscal code (12 digit instead of 11)
      Tuple2("PAGOPA|002|322201151398574181|810057500211|01", O.none)
    ].forEach(tuple => {
      expect(decodePagoPaQrCode(tuple.e1)).toEqual(tuple.e2);
    });
  });
});

describe("decodePosteDataMatrix", () => {
  it("should decode successfully a valid string", () => {
    const input =
      "codfase=NBPA;183007157000000000321200001630209310000000000138961P100085240950BSCMTT83A12L719RName Surname                           test                                                                                                                      A";

    const output = decodePosteDataMatrix(input);

    expect(O.isSome(output)).toBe(true);
  });

  it("should not decode an invalid string", () => {
    const input =
      "codfase=NBPA;1830071A7000000000321200E01630209310000000000138961P100085240950BSCMTT83A12L719RName Surname                           test                                                                                                                      A";

    const output = decodePosteDataMatrix(input);

    expect(O.isSome(output)).toBe(false);
  });

  it("should not decode a string encoded differently", () => {
    const input = "PAGOPA|002|322201151398574181|810057500211|01";
    const output = decodePosteDataMatrix(input);

    expect(O.isSome(output)).toBe(false);
  });

  it("should not decode an empty string", () => {
    const input = "";
    const output = decodePosteDataMatrix(input);

    expect(O.isSome(output)).toBe(false);
  });
});

const mockTranction: Transaction = {
  accountingStatus: 1,
  amount: { amount: 20000 },
  created: new Date(2018, 10, 30, 13, 12, 22, 30),
  description: `hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world`,
  error: false,
  fee: { amount: 123 },
  grandTotal: { amount: 32100 },
  id: 1,
  idPayment: 1,
  idPsp: 43188,
  idStatus: 3,
  idWallet: 12345,
  merchant: "merchant",
  nodoIdPayment: "nodoIdPayment",
  paymentModel: 5,
  spcNodeDescription: "spcNodeDescription",
  spcNodeStatus: 6,
  statusMessage: "statusMessage",
  success: true,
  token: "token",
  updated: undefined,
  urlCheckout3ds: "urlCheckout3ds",
  urlRedirectPSP: "urlRedirectPSP"
};

describe("getTransactionFee", () => {
  [
    Tuple2(mockTranction, `${123}`),
    Tuple2({ ...mockTranction, fee: undefined }, null),
    Tuple2({ ...mockTranction, fee: { amount: 54321 } }, `${54321}`),
    Tuple2({ ...mockTranction, fee: { amount: 0 } }, `${0}`)
  ].forEach(tuple => {
    expect(getTransactionFee(tuple.e1, f => `${f}`)).toEqual(tuple.e2);
  });
});

describe("getTransactionIUV", () => {
  [
    Tuple2(
      "/RFB/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2(
      "RFB/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2(
      "/RFA/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2(
      "RFA/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2(
      "/RFS/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2(
      "RFS/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION",
      O.some("02000000000495213")
    ),
    Tuple2("", O.none),
    Tuple2("RFC/02000000000495213/0.01/TXT/TRANSACTION DESCRIPTION", O.none),
    Tuple2("RFB/", O.none)
  ].forEach(tuple => {
    expect(getTransactionIUV(tuple.e1)).toEqual(tuple.e2);
  });
});

describe("getCodiceAvviso", () => {
  const organizationFiscalCode = "00000123456";
  [
    Tuple2<RptId, string>(
      {
        organizationFiscalCode,
        paymentNoticeNumber: {
          applicationCode: "02",
          auxDigit: "0",
          checkDigit: "78",
          iuv13: "1600203993985"
        }
      } as RptId,
      `002160020399398578`
    ),
    Tuple2<RptId, string>(
      {
        organizationFiscalCode,
        paymentNoticeNumber: {
          auxDigit: "1",
          iuv17: "16002039939851111"
        }
      } as RptId,
      `116002039939851111`
    ),
    Tuple2<RptId, string>(
      {
        organizationFiscalCode,
        paymentNoticeNumber: {
          checkDigit: "78",
          auxDigit: "2",
          iuv15: "160020399398511"
        }
      } as RptId,
      `216002039939851178`
    ),
    Tuple2<RptId, string>(
      {
        organizationFiscalCode,
        paymentNoticeNumber: {
          checkDigit: "78",
          auxDigit: "3",
          segregationCode: "55",
          iuv13: "1600203993985"
        }
      } as RptId,
      `355160020399398578`
    )
  ].forEach(tuple => {
    expect(getCodiceAvviso(tuple.e1)).toEqual(tuple.e2);
  });
});

describe("getV2ErrorMacro", () => {
  it("Should return correct macro error type given a specific error code", () => {
    [
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_CANALE_DISABILITATO", "TECHNICAL"),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_SINTASSI_EXTRAXSD", "DATA"),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_STAZIONE_INT_PA_TIMEOUT", "EC"),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_ERRORE_EMESSO_DA_PAA", "EC"),
      Tuple2<DetailV2Keys, ErrorTypes>("PAA_PAGAMENTO_IN_CORSO", "ONGOING"),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_PAGAMENTO_IN_CORSO", "ONGOING"),
      Tuple2<DetailV2Keys, ErrorTypes>("PAA_PAGAMENTO_ANNULLATO", "REVOKED"),
      Tuple2<DetailV2Keys, ErrorTypes>("PAA_PAGAMENTO_SCADUTO", "EXPIRED"),
      Tuple2<DetailV2Keys, ErrorTypes>("PAA_PAGAMENTO_DUPLICATO", "DUPLICATED"),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_PAGAMENTO_DUPLICATO", "DUPLICATED"),
      Tuple2<DetailV2Keys, ErrorTypes>(
        "PAA_PAGAMENTO_SCONOSCIUTO",
        "NOT_FOUND"
      ),
      Tuple2<DetailV2Keys, ErrorTypes>("PPT_RT_SCONOSCIUTA", "UNCOVERED")
    ].forEach(t => {
      expect(getV2ErrorMainType(t.e1)).toBe(t.e2);
    });
  });
});

describe("getErrorDescriptionV2", () => {
  it("Should return correct error description given a specific error code", () => {
    [
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_CANALE_DISABILITATO",
        I18n.t("wallet.errors.TECHNICAL")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_SINTASSI_EXTRAXSD",
        I18n.t("wallet.errors.DATA")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_STAZIONE_INT_PA_TIMEOUT",
        I18n.t("wallet.errors.EC")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_ERRORE_EMESSO_DA_PAA",
        I18n.t("wallet.errors.EC")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PAA_PAGAMENTO_IN_CORSO",
        I18n.t("wallet.errors.ONGOING")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_PAGAMENTO_IN_CORSO",
        I18n.t("wallet.errors.ONGOING")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PAA_PAGAMENTO_ANNULLATO",
        I18n.t("wallet.errors.REVOKED")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PAA_PAGAMENTO_SCADUTO",
        I18n.t("wallet.errors.EXPIRED")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PAA_PAGAMENTO_DUPLICATO",
        I18n.t("wallet.errors.DUPLICATED")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_PAGAMENTO_DUPLICATO",
        I18n.t("wallet.errors.DUPLICATED")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PAA_PAGAMENTO_SCONOSCIUTO",
        I18n.t("wallet.errors.NOT_FOUND")
      ),
      Tuple2<DetailV2Keys | undefined, string>(
        "PPT_RT_SCONOSCIUTA",
        I18n.t("wallet.errors.GENERIC_ERROR")
      ),
      Tuple2<DetailV2Keys | undefined, undefined>(undefined, undefined)
    ].forEach(t => {
      expect(getErrorDescriptionV2(t.e1)).toBe(t.e2);
    });
  });
});