teamdigitale/italia-app

View on GitHub
ts/features/messages/store/reducers/__tests__/downloads.test.ts

Summary

Maintainability
F
1 wk
Test Coverage
import * as pot from "@pagopa/ts-commons/lib/pot";
import { mockPdfAttachment } from "../../../__mocks__/attachment";
import {
  DownloadAttachmentCancel,
  DownloadAttachmentError,
  DownloadAttachmentRequest,
  DownloadAttachmentSuccess,
  clearRequestedAttachmentDownload,
  downloadAttachment,
  removeCachedAttachment
} from "../../actions";
import {
  Downloads,
  INITIAL_STATE,
  downloadedMessageAttachmentSelector,
  downloadsReducer,
  hasErrorOccourredOnRequestedDownloadSelector,
  isDownloadingMessageAttachmentSelector,
  isRequestedAttachmentDownloadSelector
} from "../downloads";
import { UIMessageId } from "../../../types";
import { GlobalState } from "../../../../../store/reducers/types";
import { appReducer } from "../../../../../store/reducers";
import { applicationChangeState } from "../../../../../store/actions/application";
import { ThirdPartyAttachment } from "../../../../../../definitions/backend/ThirdPartyAttachment";

const path = "/path/attachment.pdf";

describe("downloadedMessageAttachmentSelector", () => {
  it("Should return undefined for an unmatching messageId", () => {
    const attachmentId = "1";
    const successDownload = {
      attachment: {
        id: attachmentId
      } as ThirdPartyAttachment,
      messageId: "01HMXFQ803Q8JGQECKQF0EX6KX" as UIMessageId,
      path: "randomPath"
    } as DownloadAttachmentSuccess;
    const downloadSuccessAction = downloadAttachment.success(successDownload);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadSuccessAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return undefined for a matching messageId with an unmatching attachmentId", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const unrelatedAttachmentId = "2";
    const successDownload = {
      attachment: {
        id: unrelatedAttachmentId
      } as ThirdPartyAttachment,
      messageId,
      path: "randomPath"
    } as DownloadAttachmentSuccess;
    const downloadSuccessAction = downloadAttachment.success(successDownload);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadSuccessAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const attachmentId = "1";
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return undefined for an attachment that is loading", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const attachmentId = "1";
    const uiAttachmentRequest = {
      messageId,
      attachment: { id: attachmentId } as ThirdPartyAttachment,
      skipMixpanelTrackingOnFailure: true
    } as DownloadAttachmentRequest;
    const downloadRequestAction =
      downloadAttachment.request(uiAttachmentRequest);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadRequestAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return undefined for an attachment that got an error", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const attachmentId = "1";
    const failedDownload = {
      attachment: {
        id: attachmentId
      } as ThirdPartyAttachment,
      messageId,
      error: new Error("An error")
    } as DownloadAttachmentError;
    const downloadFailureAction = downloadAttachment.failure(failedDownload);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadFailureAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return undefined for an attachment that was cancelled before finishing the download", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const attachmentId = "1";
    const uiAttachmentCancelled = {
      messageId,
      attachment: { id: attachmentId } as ThirdPartyAttachment
    } as DownloadAttachmentCancel;
    const downloadCancelAction = downloadAttachment.cancel(
      uiAttachmentCancelled
    );
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadCancelAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return undefined for an attachment that was removed by a removeCachedAttachment action", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const attachmentId = "1";
    const successDownload = {
      attachment: {
        id: attachmentId
      } as ThirdPartyAttachment,
      messageId,
      path: "randomPath"
    } as DownloadAttachmentSuccess;
    const removedCachedAttachmentAction =
      removeCachedAttachment(successDownload);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      removedCachedAttachmentAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeUndefined();
  });
  it("Should return data for a matching downloaded attachment", () => {
    const messageId = "01HMXFE7192J01KNK02BJAPMBR" as UIMessageId;
    const attachmentId = "1";
    const downloadPath = "randomPath";
    const successDownload = {
      attachment: {
        id: attachmentId
      } as ThirdPartyAttachment,
      messageId,
      path: downloadPath
    } as DownloadAttachmentSuccess;
    const downloadSuccessAction = downloadAttachment.success(successDownload);
    const downloadsState = downloadsReducer(
      INITIAL_STATE,
      downloadSuccessAction
    );
    const globalState = {
      entities: {
        messages: {
          downloads: downloadsState
        }
      }
    } as GlobalState;
    const downloadedAttachment = downloadedMessageAttachmentSelector(
      globalState,
      messageId,
      attachmentId
    );
    expect(downloadedAttachment).toBeDefined();
    expect(downloadedAttachment?.attachment).toBeDefined();
    expect(downloadedAttachment?.attachment.id).toBe(attachmentId);
    expect(downloadedAttachment?.path).toBe(downloadPath);
  });
});

describe("downloadsReducer", () => {
  const messageId = "01HP08KKPY65CBF4TRPHGJJ1GT" as UIMessageId;

  describe("given no download", () => {
    const initialState = {};

    describe("when requesting an attachment", () => {
      const attachment = mockPdfAttachment;

      const afterRequestState = downloadsReducer(
        initialState,
        downloadAttachment.request({
          attachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );

      it("then it returns pot.loading", () => {
        expect(
          pot.isLoading(
            afterRequestState[messageId]?.[attachment.id] ?? pot.none
          )
        ).toBeTruthy();
        expect(afterRequestState.requestedDownload).toBeDefined();
        expect(afterRequestState.requestedDownload?.messageId).toBe(messageId);
        expect(afterRequestState.requestedDownload?.attachmentId).toBe(
          attachment.id
        );
      });

      describe("and the request succeeds", () => {
        it("then it returns pot.some", () => {
          expect(
            pot.isSome(
              downloadsReducer(
                afterRequestState,
                downloadAttachment.success({
                  attachment,
                  messageId,
                  path
                })
              )[messageId]?.[attachment.id] ?? pot.none
            )
          ).toBeTruthy();
          expect(afterRequestState.requestedDownload).toBeDefined();
          expect(afterRequestState.requestedDownload?.messageId).toBe(
            messageId
          );
          expect(afterRequestState.requestedDownload?.attachmentId).toBe(
            attachment.id
          );
        });
      });

      describe("and the request fails", () => {
        it("then it returns pot.error", () => {
          expect(
            pot.isError(
              downloadsReducer(
                afterRequestState,
                downloadAttachment.failure({
                  attachment,
                  messageId,
                  error: new Error()
                })
              )[messageId]?.[attachment.id] ?? pot.none
            )
          ).toBeTruthy();
          expect(afterRequestState.requestedDownload).toBeDefined();
          expect(afterRequestState.requestedDownload?.messageId).toBe(
            messageId
          );
          expect(afterRequestState.requestedDownload?.attachmentId).toBe(
            attachment.id
          );
        });
      });
    });
  });

  describe("given a downloaded attachment", () => {
    const attachment = mockPdfAttachment;
    const initialState: Downloads = {
      [messageId]: {
        [attachment.id]: pot.some({ attachment, path })
      }
    };

    describe("when clearing the attachment", () => {
      it("then it returns pot.none", () => {
        expect(
          pot.isNone(
            downloadsReducer(
              initialState,
              removeCachedAttachment({ attachment, messageId, path })
            )[messageId]?.[attachment.id] ?? pot.none
          )
        ).toBeTruthy();
        expect(initialState.requestedDownload).toBeUndefined();
      });
    });
  });

  describe("given a downloading attachment", () => {
    const attachment = mockPdfAttachment;
    const initialState = downloadsReducer(
      undefined,
      downloadAttachment.request({
        attachment,
        messageId,
        skipMixpanelTrackingOnFailure: false
      })
    );

    expect(initialState.requestedDownload).toBeDefined();
    expect(initialState.requestedDownload?.messageId).toBe(messageId);
    expect(initialState.requestedDownload?.attachmentId).toBe(attachment.id);

    it("Should return pot.none and clear the requestedDownload after a downloadAttachment.cancel action", () => {
      const cancelState = downloadsReducer(
        initialState,
        downloadAttachment.cancel({
          attachment,
          messageId
        })
      );
      const potNone = cancelState[messageId]?.[attachment.id];
      expect(potNone).toBeDefined();
      expect(pot.isNone(potNone!)).toBeTruthy();
      expect(cancelState.requestedDownload).toBeUndefined();
    });
    it("Should clear the requestedDownload after a clearRequestedAttachmentDownload action", () => {
      const cancelState = downloadsReducer(
        initialState,
        clearRequestedAttachmentDownload()
      );
      expect(cancelState.requestedDownload).toBeUndefined();
    });
  });

  describe("isDownloadingMessageAttachmentSelector", () => {
    it("should return false on initial state", () => {
      const initialState = appReducer(
        undefined,
        applicationChangeState("active")
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        initialState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return true on a matching download", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        initialState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeTruthy();
    });
    it("should return false on a messageId-unmatching download", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        initialState,
        "01HNWPGF3TY9WQYGX5JYAW816W" as UIMessageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return false on an attachmentId-unmatching download", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        initialState,
        messageId,
        "potato"
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return false on a successful downloaded attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const successState = appReducer(
        initialState,
        downloadAttachment.success({
          attachment: mockPdfAttachment,
          messageId,
          path: `file:///${mockPdfAttachment.id}.pdf`
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        successState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return false on a failed downloaded attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        failureState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return false on a cancelled downloaded attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const cancelledState = appReducer(
        initialState,
        downloadAttachment.cancel({
          attachment: mockPdfAttachment,
          messageId
        })
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        cancelledState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeFalsy();
    });
    it("should return true on a cleared stated", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const clearedState = appReducer(
        initialState,
        clearRequestedAttachmentDownload()
      );
      const isDownloadingMessage = isDownloadingMessageAttachmentSelector(
        clearedState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isDownloadingMessage).toBeTruthy();
    });
  });

  describe("hasErrorOccourredOnMessageAttachmentDownloadSelector", () => {
    it("should return false on initial state", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        initialState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeFalsy();
    });
    it("should return false on a messageId-unmatching attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        failureState,
        "01HNWQ5YDG02JFGFH9523AC04Z" as UIMessageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeFalsy();
    });
    it("should return false on an attachmentId-unmatching attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        failureState,
        messageId,
        "potato"
      );
      expect(isError).toBeFalsy();
    });
    it("should return true on a failed attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        failureState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeTruthy();
    });
    it("should return false on a successful attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.success({
          attachment: mockPdfAttachment,
          messageId,
          path: `file:///${mockPdfAttachment.id}.pdf`
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        failureState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeFalsy();
    });
    it("should return false on a cancelled attachment", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.cancel({
          attachment: mockPdfAttachment,
          messageId
        })
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        failureState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeFalsy();
    });
    it("should return false on a failed attachment after clear state", () => {
      const initialState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failureState = appReducer(
        initialState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const clearState = appReducer(
        failureState,
        clearRequestedAttachmentDownload()
      );
      const isError = hasErrorOccourredOnRequestedDownloadSelector(
        clearState,
        messageId,
        mockPdfAttachment.id
      );
      expect(isError).toBeFalsy();
    });
  });

  describe("isRequestedAttachmentDownloadSelector", () => {
    it("should return false on initial state", () => {
      const initialState = appReducer(
        undefined,
        applicationChangeState("active")
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          initialState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeFalsy();
    });
    it("should return true on matching downloading attachment", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          downloadingAttachmentState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeTruthy();
    });
    it("should return false on an messageId-unmatching downloading attachment", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          downloadingAttachmentState,
          "01HNWNXS6G2Y86HEFQ3AYSQA1Q" as UIMessageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeFalsy();
    });
    it("should return false on an attachmentId-unmatching downloading attachment", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          downloadingAttachmentState,
          messageId,
          "potato"
        );
      expect(isRequestedAttachmentDownload).toBeFalsy();
    });
    it("should return true on successful downloaded attachment", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const successfulDownloadState = appReducer(
        downloadingAttachmentState,
        downloadAttachment.success({
          attachment: mockPdfAttachment,
          messageId,
          path: `file:///${mockPdfAttachment.id}.pdf`
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          successfulDownloadState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeTruthy();
    });
    it("should return true on failed downloaded attachment", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const failedDownloadState = appReducer(
        downloadingAttachmentState,
        downloadAttachment.failure({
          attachment: mockPdfAttachment,
          messageId,
          error: new Error("")
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          failedDownloadState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeTruthy();
    });
    it("should return false on matching cancelled attachment download", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const cancelledDownloadState = appReducer(
        downloadingAttachmentState,
        downloadAttachment.cancel({
          attachment: mockPdfAttachment,
          messageId
        })
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          cancelledDownloadState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeFalsy();
    });
    it("should return false on clear requested download", () => {
      const downloadingAttachmentState = appReducer(
        undefined,
        downloadAttachment.request({
          attachment: mockPdfAttachment,
          messageId,
          skipMixpanelTrackingOnFailure: false
        })
      );
      const clearRequestedDownloadState = appReducer(
        downloadingAttachmentState,
        clearRequestedAttachmentDownload()
      );
      const isRequestedAttachmentDownload =
        isRequestedAttachmentDownloadSelector(
          clearRequestedDownloadState,
          messageId,
          mockPdfAttachment.id
        );
      expect(isRequestedAttachmentDownload).toBeFalsy();
    });
  });
});