forked from pagopa/io-app
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Redesign Servizi): [IARS-13] Isolate toggle components for servi…
…ce contact preference handling (pagopa#3178) * Extract and isolate new component for email * WIP unit tests Signed-off-by: Pietro Grandi <[email protected]> * Add new components in separate parent * Last updates before handing over * Add feature flag Signed-off-by: Pietro Grandi <[email protected]> * Minor refactoring proposal * Remove obsolete code * Add unit test for PreferenceToggleRow * Add unit test for ContactPreferencesToggles Co-authored-by: CrisTofani <[email protected]> Co-authored-by: fabriziofff <[email protected]>
- Loading branch information
1 parent
c9a3f93
commit 00ae7b4
Showing
6 changed files
with
350 additions
and
4 deletions.
There are no files selected for viewing
39 changes: 39 additions & 0 deletions
39
ts/components/services/ContactPreferencesToggles/PreferenceToggleRow.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from "react"; | ||
import { View, StyleSheet } from "react-native"; | ||
import Switch from "../../ui/Switch"; | ||
import { H4 } from "../../core/typography/H4"; | ||
import { IOStyles } from "../../core/variables/IOStyles"; | ||
|
||
type Props = { | ||
label: string; | ||
onPress: (value: boolean) => void; | ||
value: boolean; | ||
testID?: string; | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
row: { | ||
flexDirection: "row", | ||
flex: 1, | ||
justifyContent: "space-between", | ||
paddingVertical: 12 | ||
} | ||
}); | ||
|
||
const PreferenceToggleRow = ({ | ||
label, | ||
onPress, | ||
value, | ||
testID = "preference-toggle-row" | ||
}: Props): React.ReactElement => ( | ||
<View style={[styles.row]}> | ||
<View style={IOStyles.flex}> | ||
<H4 weight={"Regular"} color={"bluegreyDark"}> | ||
{label} | ||
</H4> | ||
</View> | ||
<Switch value={value} onValueChange={onPress} testID={testID} /> | ||
</View> | ||
); | ||
|
||
export default PreferenceToggleRow; |
80 changes: 80 additions & 0 deletions
80
ts/components/services/ContactPreferencesToggles/__test__/ContactPreferencesToggles.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import React from "react"; | ||
import { NavigationParams } from "react-navigation"; | ||
import { createStore } from "redux"; | ||
import { NotificationChannelEnum } from "../../../../../definitions/backend/NotificationChannel"; | ||
import { applicationChangeState } from "../../../../store/actions/application"; | ||
import { GlobalState } from "../../../../store/reducers/types"; | ||
import { renderScreenFakeNavRedux } from "../../../../utils/testWrapper"; | ||
import { appReducer } from "../../../../store/reducers"; | ||
import ROUTES from "../../../../navigation/routes"; | ||
|
||
import ContactPreferencesToggles from "../index"; | ||
|
||
jest.useFakeTimers(); | ||
|
||
describe("ContactPreferencesToggles component", () => { | ||
describe("when channels are not defined", () => { | ||
it("should render all the switches", () => { | ||
const component = renderComponent({}); | ||
expect( | ||
component.getByTestId("contact-preferences-inbox-switch") | ||
).toBeDefined(); | ||
expect( | ||
component.getByTestId("contact-preferences-webhook-switch") | ||
).toBeDefined(); | ||
expect( | ||
component.getByTestId("contact-preferences-email-switch") | ||
).toBeDefined(); | ||
}); | ||
}); | ||
|
||
describe("when channels is an empty array", () => { | ||
it("should render the INBOX switch", () => { | ||
const component = renderComponent({ channels: [] }); | ||
expect( | ||
component.getByTestId("contact-preferences-inbox-switch") | ||
).toBeDefined(); | ||
}); | ||
it("should not render WEBHOOK and EMAIL switches", () => { | ||
const component = renderComponent({ channels: [] }); | ||
expect( | ||
component.queryByTestId("contact-preferences-webhook-switch") | ||
).toBeNull(); | ||
expect( | ||
component.queryByTestId("contact-preferences-email-switch") | ||
).toBeNull(); | ||
}); | ||
}); | ||
|
||
describe("when channels contains all the items ", () => { | ||
it("should render all the switches", () => { | ||
const component = renderComponent({ | ||
channels: [ | ||
NotificationChannelEnum.EMAIL, | ||
NotificationChannelEnum.WEBHOOK | ||
] | ||
}); | ||
expect( | ||
component.getByTestId("contact-preferences-inbox-switch") | ||
).toBeDefined(); | ||
expect( | ||
component.getByTestId("contact-preferences-webhook-switch") | ||
).toBeDefined(); | ||
expect( | ||
component.getByTestId("contact-preferences-email-switch") | ||
).toBeDefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
function renderComponent(options: { | ||
channels?: ReadonlyArray<NotificationChannelEnum>; | ||
}) { | ||
const globalState = appReducer(undefined, applicationChangeState("active")); | ||
return renderScreenFakeNavRedux<GlobalState, NavigationParams>( | ||
() => <ContactPreferencesToggles {...options} />, | ||
ROUTES.WALLET_CHECKOUT_3DS_SCREEN, | ||
{}, | ||
createStore(appReducer, globalState as any) | ||
); | ||
} |
52 changes: 52 additions & 0 deletions
52
ts/components/services/ContactPreferencesToggles/__test__/PreferenceToggleRow.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React from "react"; | ||
import { render, fireEvent } from "@testing-library/react-native"; | ||
|
||
import PreferenceToggleRow from "../PreferenceToggleRow"; | ||
|
||
describe("PreferenceToggleRow component", () => { | ||
const options = { | ||
label: "Push Notifications", | ||
value: true, | ||
onPress: jest.fn() | ||
}; | ||
it("should match the snapshot", () => { | ||
const component = renderComponent(options); | ||
expect(component.toJSON()).toMatchSnapshot(); | ||
}); | ||
|
||
it("should show the label", () => { | ||
const component = renderComponent(options); | ||
expect(component.getByText("Push Notifications")).toBeDefined(); | ||
}); | ||
it("should expose a working switch", () => { | ||
const component = renderComponent(options); | ||
const switchComponent = component.getByRole("switch"); | ||
expect(switchComponent).toBeDefined(); | ||
fireEvent(switchComponent, "onValueChange", false); | ||
expect(options.onPress).toHaveBeenCalledWith(false); | ||
}); | ||
it("should use a default testID", () => { | ||
const component = renderComponent(options); | ||
expect(component.getByTestId("preference-toggle-row")).toBeDefined(); | ||
}); | ||
describe("when a testID is passed", () => { | ||
it("should honour the property", () => { | ||
const component = renderComponent({ ...options, testID: "new-test-id" }); | ||
expect(component.getByTestId("new-test-id")).toBeDefined(); | ||
}); | ||
}); | ||
}); | ||
|
||
function renderComponent( | ||
options: Partial<Parameters<typeof PreferenceToggleRow>[0]> | ||
) { | ||
return render( | ||
<PreferenceToggleRow | ||
label="default label" | ||
value={true} | ||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
onPress={() => {}} | ||
{...options} | ||
/> | ||
); | ||
} |
74 changes: 74 additions & 0 deletions
74
...rvices/ContactPreferencesToggles/__test__/__snapshots__/PreferenceToggleRow.test.tsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`PreferenceToggleRow component should match the snapshot 1`] = ` | ||
<View | ||
style={ | ||
Array [ | ||
Object { | ||
"flex": 1, | ||
"flexDirection": "row", | ||
"justifyContent": "space-between", | ||
"paddingVertical": 12, | ||
}, | ||
] | ||
} | ||
> | ||
<View | ||
style={ | ||
Object { | ||
"flex": 1, | ||
} | ||
} | ||
> | ||
<Text | ||
color="bluegreyDark" | ||
font="TitilliumWeb" | ||
fontStyle={ | ||
Object { | ||
"fontSize": 16, | ||
} | ||
} | ||
style={ | ||
Array [ | ||
Object { | ||
"fontSize": 16, | ||
}, | ||
Object { | ||
"color": "#17324D", | ||
"fontFamily": "Titillium Web", | ||
"fontStyle": "normal", | ||
"fontWeight": "400", | ||
}, | ||
] | ||
} | ||
weight="Regular" | ||
weightColorFactory={[Function]} | ||
> | ||
Push Notifications | ||
</Text> | ||
</View> | ||
<RCTSwitch | ||
accessibilityRole="switch" | ||
onChange={[Function]} | ||
onResponderTerminationRequest={[Function]} | ||
onStartShouldSetResponder={[Function]} | ||
onTintColor="#0073E6" | ||
style={ | ||
Array [ | ||
Object { | ||
"height": 31, | ||
"width": 51, | ||
}, | ||
Object { | ||
"marginBottom": -5, | ||
"marginTop": -5, | ||
}, | ||
] | ||
} | ||
testID="preference-toggle-row" | ||
thumbTintColor="default" | ||
tintColor="default" | ||
value={true} | ||
/> | ||
</View> | ||
`; |
91 changes: 91 additions & 0 deletions
91
ts/components/services/ContactPreferencesToggles/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import React, { useState } from "react"; | ||
import { connect } from "react-redux"; | ||
import { fromNullable } from "fp-ts/lib/Option"; | ||
|
||
import { GlobalState } from "../../../store/reducers/types"; | ||
import I18n from "../../../i18n"; | ||
import ItemSeparatorComponent from "../../ItemSeparatorComponent"; | ||
import { NotificationChannelEnum } from "../../../../definitions/backend/NotificationChannel"; | ||
import PreferenceToggleRow from "./PreferenceToggleRow"; | ||
|
||
type Item = "email" | "push" | "inbox"; | ||
|
||
type Props = { | ||
channels?: ReadonlyArray<NotificationChannelEnum>; | ||
} & ReturnType<typeof mapStateToProps>; | ||
|
||
const ContactPreferencesToggle: React.FC<Props> = (props: Props) => { | ||
// functions from actions | ||
const onValueChange: (item: Item, value: boolean) => void = (_item, _value) => | ||
undefined; | ||
|
||
/* | ||
* TODO State should be removed when data will be available from store | ||
*/ | ||
const [inboxSwitched, setInboxSwitched] = useState(true); | ||
const [pushSwitched, setPushSwitched] = useState(true); | ||
const [emailSwitched, setEmailSwitched] = useState(true); | ||
|
||
const onInboxValueChange = (value: boolean) => { | ||
onValueChange("inbox", value); | ||
setInboxSwitched(value); | ||
}; | ||
|
||
const hasChannel = (channel: NotificationChannelEnum) => | ||
fromNullable(props.channels) | ||
.map(anc => anc.indexOf(channel) !== -1) | ||
.getOrElse(true); | ||
|
||
const onPushValueChange = (value: boolean) => { | ||
onValueChange("push", value); | ||
setPushSwitched(value); | ||
}; | ||
|
||
const onEmailValueChange = (value: boolean) => { | ||
onValueChange("email", value); | ||
setEmailSwitched(value); | ||
}; | ||
|
||
return ( | ||
<> | ||
<PreferenceToggleRow | ||
label={ | ||
inboxSwitched | ||
? I18n.t("services.serviceIsEnabled") | ||
: I18n.t("services.serviceNotEnabled") | ||
} | ||
onPress={onInboxValueChange} | ||
value={inboxSwitched} | ||
testID={"contact-preferences-inbox-switch"} | ||
/> | ||
<ItemSeparatorComponent noPadded /> | ||
{hasChannel(NotificationChannelEnum.WEBHOOK) && ( | ||
<> | ||
<PreferenceToggleRow | ||
label={I18n.t("services.pushNotifications")} | ||
onPress={onPushValueChange} | ||
value={pushSwitched} | ||
testID={"contact-preferences-webhook-switch"} | ||
/> | ||
<ItemSeparatorComponent noPadded /> | ||
</> | ||
)} | ||
|
||
{hasChannel(NotificationChannelEnum.EMAIL) && ( | ||
<> | ||
<PreferenceToggleRow | ||
label={I18n.t("services.emailForwarding")} | ||
onPress={onEmailValueChange} | ||
value={emailSwitched} | ||
testID={"contact-preferences-email-switch"} | ||
/> | ||
<ItemSeparatorComponent noPadded /> | ||
</> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
const mapStateToProps = (_state: GlobalState) => ({}); | ||
|
||
export default connect(mapStateToProps)(ContactPreferencesToggle); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters