Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#173510346] Fixes test 2e2 #1959

Merged
merged 18 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions ts/components/messages/MessageDetailCTABar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CreatedMessageWithContent } from "../../../definitions/backend/CreatedM
import { ServicePublic } from "../../../definitions/backend/ServicePublic";
import { ReduxProps } from "../../store/actions/types";
import { PaidReason } from "../../store/reducers/entities/payments";
import { isExpired, paymentExpirationInfo } from "../../utils/messages";
import { getCTA, isExpired, paymentExpirationInfo } from "../../utils/messages";
import CalendarEventButton from "./CalendarEventButton";
import { MessageNestedCTABar } from "./MessageNestedCTABar";
import PaymentButton from "./PaymentButton";
Expand Down Expand Up @@ -89,16 +89,14 @@ class MessageDetailCTABar extends React.PureComponent<Props> {
{paymentButton}
</View>
);
const nestedCTAs = (
<MessageNestedCTABar
message={this.props.message}
dispatch={this.props.dispatch}
xsmall={false}
/>
);
const footer2 = nestedCTAs && (
const maybeCtas = getCTA(this.props.message);
const footer2 = maybeCtas.isSome() && (
<View footer={true} style={styles.row}>
{nestedCTAs}
<MessageNestedCTABar
ctas={maybeCtas.value}
dispatch={this.props.dispatch}
xsmall={false}
/>
</View>
);
return (
Expand Down
18 changes: 10 additions & 8 deletions ts/components/messages/MessageListCTABar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ReduxProps } from "../../store/actions/types";
import { PaidReason } from "../../store/reducers/entities/payments";
import customVariables from "../../theme/variables";
import { formatDateAsDay, formatDateAsMonth } from "../../utils/dates";
import { isExpired, paymentExpirationInfo } from "../../utils/messages";
import { getCTA, isExpired, paymentExpirationInfo } from "../../utils/messages";
import CalendarEventButton from "./CalendarEventButton";
import CalendarIconComponent from "./CalendarIconComponent";
import { MessageNestedCTABar } from "./MessageNestedCTABar";
Expand Down Expand Up @@ -126,14 +126,16 @@ class MessageListCTABar extends React.PureComponent<Props> {
public render() {
const calendarIcon = this.renderCalendarIcon();
const calendarEventButton = this.renderCalendarEventButton();
const maybeCTA = getCTA(this.props.message);
// payment CTA has priority to nested CTA
const nestedCTA = !this.hasPaymentData ? (
<MessageNestedCTABar
message={this.props.message}
dispatch={this.props.dispatch}
xsmall={true}
/>
) : null;
const nestedCTA =
!this.hasPaymentData && maybeCTA.isSome() ? (
<MessageNestedCTABar
ctas={maybeCTA.value}
dispatch={this.props.dispatch}
xsmall={true}
/>
) : null;
const content = nestedCTA || (
<>
{calendarIcon}
Expand Down
73 changes: 30 additions & 43 deletions ts/components/messages/MessageNestedCTABar.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,46 @@
import { View } from "native-base";
import React from "react";
import React, { ReactElement } from "react";
import { Dispatch } from "redux";
import { CreatedMessageWithContent } from "../../../definitions/backend/CreatedMessageWithContent";
import { CTA } from "../../types/MessageCTA";
import {
getCTA,
handleCtaAction,
hasCTAValidActions,
isCtaActionValid
} from "../../utils/messages";
import { CTA, CTAS } from "../../types/MessageCTA";
import { handleCtaAction, isCtaActionValid } from "../../utils/messages";
import { MessageNestedCtaButton } from "./MessageNestedCtaButton";

type Props = {
message: CreatedMessageWithContent;
ctas: CTAS;
xsmall: boolean;
dispatch: Dispatch;
};

// render cta1 and cta2 if they are defined in the message content as nested front-matter
export const MessageNestedCTABar: React.FunctionComponent<Props> = (
props: Props
) => {
): ReactElement => {
const handleCTAPress = (cta: CTA) => {
handleCtaAction(cta, props.dispatch);
};

const maybeNestedCTA = getCTA(props.message);
if (maybeNestedCTA.isSome()) {
const ctas = maybeNestedCTA.value;
if (hasCTAValidActions(ctas)) {
const cta2 = ctas.cta_2 &&
isCtaActionValid(ctas.cta_2) && (
<MessageNestedCtaButton
cta={ctas.cta_2}
xsmall={props.xsmall}
primary={false}
onCTAPress={handleCTAPress}
/>
);
const cta1 = isCtaActionValid(ctas.cta_1) && (
<MessageNestedCtaButton
cta={ctas.cta_1}
primary={true}
xsmall={props.xsmall}
onCTAPress={handleCTAPress}
/>
);
return (
<>
{cta2}
{cta2 && <View hspacer={true} small={true} />}
{cta1}
</>
);
}
}
return null;
const { ctas } = props;
const cta2 = ctas.cta_2 &&
isCtaActionValid(ctas.cta_2) && (
<MessageNestedCtaButton
cta={ctas.cta_2}
xsmall={props.xsmall}
primary={false}
onCTAPress={handleCTAPress}
/>
);
const cta1 = isCtaActionValid(ctas.cta_1) && (
<MessageNestedCtaButton
cta={ctas.cta_1}
primary={true}
xsmall={props.xsmall}
onCTAPress={handleCTAPress}
/>
);
return (
<>
{cta2}
{cta2 && <View hspacer={true} small={true} />}
{cta1}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Either, left, right } from "fp-ts/lib/Either";
import { none, Option, some } from "fp-ts/lib/Option";
import { readableReport } from "italia-ts-commons/lib/reporters";
import { Millisecond } from "italia-ts-commons/lib/units";
import { call, Effect } from "redux-saga/effects";
import { ActionType } from "typesafe-actions";
import { BonusActivationStatusEnum } from "../../../../../../definitions/bonus_vacanze/BonusActivationStatus";
import { BonusActivationWithQrCode } from "../../../../../../definitions/bonus_vacanze/BonusActivationWithQrCode";
import { SagaCallReturnType } from "../../../../../types/utils";
import { readablePrivacyReport } from "../../../../../utils/reporters";
import { startTimer } from "../../../../../utils/timer";
import { BackendBonusVacanze } from "../../../api/backendBonusVacanze";
import { activateBonusVacanze } from "../../actions/bonusVacanze";
Expand Down Expand Up @@ -44,7 +45,18 @@ function* getBonusActivation(
if (getLatestBonusVacanzeFromIdResult.isRight()) {
// 200 -> we got the check result, polling must be stopped
if (getLatestBonusVacanzeFromIdResult.value.status === 200) {
return right(getLatestBonusVacanzeFromIdResult.value.value);
const activation = getLatestBonusVacanzeFromIdResult.value.value;
switch (activation.status) {
// we got some error, stop polling
case BonusActivationStatusEnum.PROCESSING:
return left(none);
Comment on lines +51 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the user will see the generic error page (cancel / retry). Is it right when in processing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabriziofff
The comment is misleading. In that case we should continue to polling.
Do you confirm?
update within bd8a090

Copy link
Contributor

@fabriziofff fabriziofff Jun 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

            if (
              bonusActivationFromIdResult.isLeft() &&
              bonusActivationFromIdResult.value.isSome()
            ) {
              throw bonusActivationFromIdResult.value;
            }

If I understand right when getBonusActivation return any left value, the polling is stopped and a activateBonusVacanze.failure(e) is dispatched. So all the switch cases will stop the polling. It is right?
EDIT: nvm, left(none) will continue the polling, I understand now!

case BonusActivationStatusEnum.FAILED:
// blocking error
return left(some(new Error("Bonus Activation failed")));
default:
// active
return right(getLatestBonusVacanzeFromIdResult.value.value);
}
}
// Request not found - polling must be stopped
if (getLatestBonusVacanzeFromIdResult.value.status === 404) {
Expand All @@ -55,7 +67,9 @@ function* getBonusActivation(
} else {
// we got some error on decoding, stop polling
return left(
some(Error(readableReport(getLatestBonusVacanzeFromIdResult.value)))
some(
Error(readablePrivacyReport(getLatestBonusVacanzeFromIdResult.value))
)
);
}
} catch (e) {
Expand Down Expand Up @@ -120,6 +134,12 @@ export const bonusActivationSaga = (
}
}
}
// 202 -> still processing
if (startBonusActivationProcedureResult.value.status === 202) {
return activateBonusVacanze.success({
status: BonusActivationProgressEnum.TIMEOUT
});
}
// 409 -> Cannot activate a new bonus because another bonus related to this user was found.
// 403 -> Eligibility Expired
else if (status === 409 || status === 403) {
Expand All @@ -132,7 +152,9 @@ export const bonusActivationSaga = (
);
}
// decoding failure
throw Error(readableReport(startBonusActivationProcedureResult.value));
throw Error(
readablePrivacyReport(startBonusActivationProcedureResult.value)
);
} catch (e) {
return activateBonusVacanze.failure(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Either, left, right } from "fp-ts/lib/Either";
import { none, Option, some } from "fp-ts/lib/Option";
import { readableReport } from "italia-ts-commons/lib/reporters";
import { Millisecond } from "italia-ts-commons/lib/units";
import { call, Effect, put } from "redux-saga/effects";
import { ActionType } from "typesafe-actions";
Expand All @@ -10,6 +9,7 @@ import { EligibilityCheckSuccess } from "../../../../../../definitions/bonus_vac
import { EligibilityCheckSuccessConflict } from "../../../../../../definitions/bonus_vacanze/EligibilityCheckSuccessConflict";
import { EligibilityCheckSuccessEligible } from "../../../../../../definitions/bonus_vacanze/EligibilityCheckSuccessEligible";
import { SagaCallReturnType } from "../../../../../types/utils";
import { readablePrivacyReport } from "../../../../../utils/reporters";
import { startTimer } from "../../../../../utils/timer";
import { BackendBonusVacanze } from "../../../api/backendBonusVacanze";
import {
Expand Down Expand Up @@ -74,7 +74,9 @@ function* getCheckBonusEligibilitySaga(
return left(none);
} else {
// we got some error on decoding, stop polling
return left(some(Error(readableReport(eligibilityCheckResult.value))));
return left(
some(Error(readablePrivacyReport(eligibilityCheckResult.value)))
);
}
} catch (e) {
return left(none);
Expand Down Expand Up @@ -107,16 +109,6 @@ export const bonusEligibilitySaga = (
Effect | ActionType<typeof checkBonusVacanzeEligibility>
> {
try {
// before activate, make an optimistic check, maybe the isee result is already available
const firstCheck = yield call(
executeGetEligibilityCheck(getBonusEligibilityCheck)
);
if (firstCheck.isRight()) {
return checkBonusVacanzeEligibility.success({
check: firstCheck.value,
status: eligibilityResultToEnum(firstCheck.value)
});
}
const startEligibilityResult: SagaCallReturnType<
typeof startBonusEligibilityCheck
> = yield call(startBonusEligibilityCheck, {});
Expand Down Expand Up @@ -176,7 +168,7 @@ export const bonusEligibilitySaga = (

throw Error(`response status ${startEligibilityResult.value.status}`);
} else {
throw Error(readableReport(startEligibilityResult.value));
throw Error(readablePrivacyReport(startEligibilityResult.value));
}
} catch (e) {
return checkBonusVacanzeEligibility.failure(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readableReport } from "italia-ts-commons/lib/reporters";
import { SagaIterator } from "redux-saga";
import { all, call, put } from "redux-saga/effects";
import { SagaCallReturnType } from "../../../../types/utils";
import { readablePrivacyReport } from "../../../../utils/reporters";
import { BackendBonusVacanze } from "../../api/backendBonusVacanze";
import {
loadAllBonusActivations,
Expand Down Expand Up @@ -30,7 +30,7 @@ export function* handleLoadAllBonusActivations(
`response status ${allBonusActivationsResponse.value.status}`
);
} else {
throw Error(readableReport(allBonusActivationsResponse.value));
throw Error(readablePrivacyReport(allBonusActivationsResponse.value));
}
} catch (e) {
yield put(loadAllBonusActivations.failure(e));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { readableReport } from "italia-ts-commons/lib/reporters";
import { SagaIterator } from "redux-saga";
import { call, put } from "redux-saga/effects";
import { ActionType } from "typesafe-actions";
import { SagaCallReturnType } from "../../../../types/utils";
import { readablePrivacyReport } from "../../../../utils/reporters";
import { BackendBonusVacanze } from "../../api/backendBonusVacanze";
import { loadBonusVacanzeFromId } from "../actions/bonusVacanze";

Expand All @@ -26,7 +26,7 @@ export function* handleLoadBonusVacanzeFromId(
}
throw Error(`response status ${bonusVacanzeResponse.value.status}`);
} else {
throw Error(readableReport(bonusVacanzeResponse.value));
throw Error(readablePrivacyReport(bonusVacanzeResponse.value));
}
} catch (e) {
yield put(loadBonusVacanzeFromId.failure({ error: e, id: action.payload }));
Expand Down
22 changes: 2 additions & 20 deletions ts/utils/__tests__/messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe("getCTA", () => {
);
});

it("should have 1 valid CTA", () => {
it("should not have valid CTA (action is malformed)", () => {
const CTA_1 = `---
it:
cta_1:
Expand All @@ -86,25 +86,7 @@ some noise`;
},
"it"
);
expect(maybeCTA.isSome()).toBeTruthy();
if (maybeCTA.isSome()) {
const ctas = maybeCTA.value;
expect(ctas.cta_1).toBeDefined();
expect(ctas.cta_2).not.toBeDefined();
}

const maybeCTAEn = getCTA(
{
...messageWithContent,
content: {
...messageWithContent.content,
markdown: CTA_1 as MessageBodyMarkdown
}
},
"en"
);
// this is because it fallbacks on the next locale supported (it in this case)
expect(maybeCTAEn.isSome()).toBeTruthy();
expect(maybeCTA.isNone());
});

it("should not have a valid CTA", () => {
Expand Down
Loading