teamdigitale/italia-app

View on GitHub
ts/screens/profile/__test__/ProfileDataScreen.test.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import React from "react";
import { fireEvent } from "@testing-library/react-native";
import { FiscalCode } from "@pagopa/ts-commons/lib/strings";
import { PreloadedState, createStore } from "redux";
import I18n from "../../../i18n";
import ROUTES from "../../../navigation/routes";
import { applicationChangeState } from "../../../store/actions/application";
import { appReducer } from "../../../store/reducers";
import {
  profileEmailSelector,
  profileNameSurnameSelector
} from "../../../store/reducers/profile";
import { GlobalState } from "../../../store/reducers/types";
import { renderScreenWithNavigationStoreContext } from "../../../utils/testWrapper";
import ProfileDataScreen from "../ProfileDataScreen";
import { EmailAddress } from "../../../../definitions/backend/EmailAddress";
import { profileLoadSuccess } from "../../../store/actions/profile";
import { ServicesPreferencesModeEnum } from "../../../../definitions/backend/ServicesPreferencesMode";

const profileWithoutEmail = {
  is_inbox_enabled: true,
  is_email_enabled: true,
  is_webhook_enabled: true,
  is_email_already_taken: false,
  family_name: "Red",
  fiscal_code: "FiscalCode" as FiscalCode,
  has_profile: true,
  name: "Tom",
  service_preferences_settings: { mode: ServicesPreferencesModeEnum.AUTO },
  version: 1
};
const mockNavigate = jest.fn();

jest.mock("@react-navigation/native", () => {
  const actualNav = jest.requireActual("@react-navigation/native");
  return {
    ...actualNav,
    useNavigation: () => ({
      ...actualNav.useNavigation(),
      navigate: mockNavigate
    })
  };
});

describe("Test ProfileDataScreen", () => {
  jest.useFakeTimers();
  afterEach(jest.clearAllMocks);

  it("should be not null", () => {
    const { component } = renderComponent();

    expect(component).not.toBeNull();
  });
  it("should render H1 component with title and H4 component with subtitle", () => {
    const { component } = renderComponent();

    expect(
      // With the new navbar we have two titles.
      // The second one is the larger one.
      // The first one is the smaller one that is shown when scrolling.
      component.queryAllByText(I18n.t("profile.data.title"))[1]
    ).not.toBeNull();
    expect(
      component.queryByText(I18n.t("profile.data.subtitle"))
    ).not.toBeNull();
  });
  it("should render ListItemComponent insert or edit email with the right title and subtitle", () => {
    const { component, store } = renderComponent();

    expect(component.queryByTestId("insert-or-edit-email")).not.toBeNull();
    expect(
      // With the new navbar we have two titles.
      // The second one is the larger one.
      // The first one is the smaller one that is shown when scrolling.
      component.queryAllByText(I18n.t("profile.data.title"))[1]
    ).not.toBeNull();
    expect(
      component.queryByText(
        pipe(
          profileEmailSelector(store.getState()),
          O.getOrElse(() => I18n.t("global.remoteStates.notAvailable"))
        )
      )
    ).not.toBeNull();
  });
  it("when press ListItemComponent insert or edit email, if user has email should navigate to EmailReadScreen else should navigate to EmailInsertScreen", () => {
    const { component } = renderComponent();

    const listItemComponent = component.getByTestId("insert-or-edit-email");
    expect(listItemComponent).not.toBeNull();
    fireEvent.press(listItemComponent);
  });
  it("should render ListItemComponent name and surname with the right title and subtitle", () => {
    const { component, store } = renderComponent();

    const nameSurname = profileNameSurnameSelector(store.getState());
    const listItemComponent = component.queryByTestId("name-surname");
    if (nameSurname) {
      expect(listItemComponent).not.toBeNull();
      expect(listItemComponent).toHaveTextContent(
        I18n.t("profile.data.list.nameSurname")
      );
      expect(listItemComponent).toHaveTextContent(nameSurname);
    } else {
      expect(listItemComponent).toBeNull();
    }
  });
  it("Should not navigate since profile has no email", () => {
    const { component, store } = renderComponent();
    store.dispatch(profileLoadSuccess(profileWithoutEmail));
    const { getByTestId } = component;
    const editEmailButton = getByTestId(/insert-or-edit-email-cta/);

    fireEvent.press(editEmailButton);

    expect(mockNavigate).not.toHaveBeenCalled();
  });
  it("Should navigate to the Insert Email Screen", () => {
    const { component, store } = renderComponent();
    store.dispatch(
      profileLoadSuccess({
        ...profileWithoutEmail,
        email: "this@email.it" as EmailAddress
      })
    );
    const { getByTestId } = component;
    const editEmailButton = getByTestId(/insert-or-edit-email-cta/);

    fireEvent.press(editEmailButton);

    expect(mockNavigate).toHaveBeenCalledTimes(1);
    expect(mockNavigate).toHaveBeenCalledWith(ROUTES.PROFILE_NAVIGATOR, {
      screen: ROUTES.INSERT_EMAIL_SCREEN,
      params: {
        isOnboarding: false
      }
    });
  });
});

const renderComponent = () => {
  const globalState = appReducer(
    undefined,
    applicationChangeState("active")
  ) as PreloadedState<GlobalState>;
  const store = createStore(appReducer, globalState);

  return {
    component: renderScreenWithNavigationStoreContext<GlobalState>(
      () => <ProfileDataScreen />,
      ROUTES.PROFILE_DATA,
      {},
      store
    ),
    store
  };
};