Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Telefonica/mistica-web into WEB-2056
Browse files Browse the repository at this point in the history
-navigation-bar-menu
  • Loading branch information
marcoskolodny committed Oct 31, 2024
2 parents a848552 + fda424e commit aec3ec1
Show file tree
Hide file tree
Showing 14 changed files with 570 additions and 19 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions src/__screenshot_tests__/input-fields-screenshot-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,28 @@ test.each`
expect(await fieldWrapper.screenshot()).toMatchImageSnapshot();
});

test.each`
skin | number
${'Vivo'} | ${'2145678901'}
${'Vivo'} | ${'+34654834455'}
${'Movistar'} | ${'654834455'}
`('PhoneNumberFieldLite - $number in $skin skin', async ({skin, number}) => {
await openStoryPage({
id: 'components-input-fields-phonenumberfieldlite--uncontrolled',
device: 'MOBILE_IOS',
skin,
args: {defaultValue: number},
});

const fieldWrapper = await screen.findByTestId('phone-number-field-lite');
const field = await screen.findByLabelText('Label');

await field.click({clickCount: 3});
await field.type(number);

expect(await fieldWrapper.screenshot()).toMatchImageSnapshot();
});

test('CreditCardExpirationField', async () => {
await openStoryPage({
id: 'components-input-fields-creditcardexpirationfield--uncontrolled',
Expand Down
170 changes: 170 additions & 0 deletions src/__stories__/phone-number-field-lite-story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import * as React from 'react';
import {Box, Text1, Stack, ResponsiveLayout, PhoneNumberFieldLite, Boxed} from '..';
import {inspect} from 'util';
import {phoneNumbersList} from './helpers';

export default {
title: 'Components/Input fields/PhoneNumberFieldLite',
parameters: {fullScreen: true},
};

const getPhoneNumberSuggestions = (value: string) =>
phoneNumbersList
.filter((s) => String(s).toLocaleLowerCase().startsWith(value.toLocaleLowerCase()))
.slice(0, 5);

interface PhoneNumberFieldBaseArgs {
label: string;
placeholder: string;
prefix: string;
helperText: string;
error: boolean;
inverse: boolean;
optional: boolean;
disabled: boolean;
readOnly: boolean;
preventCopy: boolean;
}

const defaultBaseArgs: PhoneNumberFieldBaseArgs = {
label: 'Label',
placeholder: '',
prefix: '',
helperText: '',
error: false,
inverse: false,
optional: false,
disabled: false,
readOnly: false,
preventCopy: false,
};

interface PhoneNumberFieldControlledArgs extends PhoneNumberFieldBaseArgs {
initialValue: string;
suggestions: boolean;
}

const Description = () => {
return (
<Boxed>
<Box padding={16}>
<Stack space={16}>
<div>
This is a "light" version of the PhoneNumberField component. It does not use google's
libphonenumber library to reduce bundle size.
</div>
<Stack space={8}>
<div>- Only supported countries are formatted</div>
<div>- Not all phone number types are formatted</div>
<div>- Numbers in E164 are returned unformatted</div>
<div>
- A custom formatter can be provided via props and the formatter used by this
component is exported as `formatPhoneLite`
</div>
</Stack>
</Stack>
</Box>
</Boxed>
);
};

export const Controlled: StoryComponent<PhoneNumberFieldControlledArgs> = ({
inverse,
initialValue,
suggestions,
...rest
}) => {
const [rawValue, setRawValue] = React.useState<any>(initialValue);
const [value, setValue] = React.useState<any>(undefined);

return (
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth>
<Box padding={16}>
<Stack space={16}>
<Description />
<PhoneNumberFieldLite
value={rawValue}
onChangeValue={(value, rawValue) => {
setValue(value);
setRawValue(rawValue);
}}
name="phoneNumber"
autoComplete="off"
dataAttributes={{testid: 'phone-number-field-lite'}}
getSuggestions={suggestions ? getPhoneNumberSuggestions : undefined}
{...rest}
/>
<Stack space={8}>
<Text1 regular>
value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`}
</Text1>
<Text1 regular>
rawValue:{' '}
{typeof rawValue === 'undefined'
? ''
: `(${typeof rawValue}) ${inspect(rawValue)}`}
</Text1>
</Stack>
</Stack>
</Box>
</ResponsiveLayout>
);
};

Controlled.storyName = 'controlled';
Controlled.args = {
initialValue: '654834455',
...defaultBaseArgs,
suggestions: false,
};

interface PhoneNumberFieldUncontrolledArgs extends PhoneNumberFieldBaseArgs {
defaultValue: string;
}

export const Uncontrolled: StoryComponent<PhoneNumberFieldUncontrolledArgs> = ({
inverse,
defaultValue,
...rest
}) => {
const [rawValue, setRawValue] = React.useState<any>(undefined);
const [value, setValue] = React.useState<any>(undefined);

return (
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth>
<Box padding={16}>
<Stack space={16}>
<Description />
<PhoneNumberFieldLite
defaultValue={defaultValue}
onChangeValue={(value, rawValue) => {
setValue(value);
setRawValue(rawValue);
}}
name="phoneNumber"
autoComplete="off"
dataAttributes={{testid: 'phone-number-field-lite'}}
{...rest}
/>
<Stack space={8}>
<Text1 regular>
value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`}
</Text1>
<Text1 regular>
rawValue:{' '}
{typeof rawValue === 'undefined'
? ''
: `(${typeof rawValue}) ${inspect(rawValue)}`}
</Text1>
</Stack>
</Stack>
</Box>
</ResponsiveLayout>
);
};

Uncontrolled.storyName = 'uncontrolled';
Uncontrolled.args = {
defaultValue: '654834455',
...defaultBaseArgs,
};
4 changes: 2 additions & 2 deletions src/__stories__/phone-number-field-story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const Controlled: StoryComponent<PhoneNumberFieldControlledArgs> = ({
const [value, setValue] = React.useState<any>(undefined);

return (
<ResponsiveLayout isInverse={inverse} fullWidth>
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth>
<Box padding={16}>
<Stack space={16}>
<PhoneNumberField
Expand Down Expand Up @@ -108,7 +108,7 @@ export const Uncontrolled: StoryComponent<PhoneNumberFieldUncontrolledArgs> = ({
const [value, setValue] = React.useState<any>(undefined);

return (
<ResponsiveLayout isInverse={inverse} fullWidth>
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth>
<Box padding={16}>
<Stack space={16}>
<PhoneNumberField
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/hooks-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const INITIAL_BODY_STYLES = 'background: red;';
const DISABLED_BODY_STYLES =
INITIAL_BODY_STYLES +
' ' +
'overflow: hidden; overflow-y: scroll; position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px;';
'overflow: hidden; overflow-y: scroll; position: fixed; top: 0px; left: 0px; right: 0px;';

const DisableScroll = () => {
useDisableBodyScroll(true);
Expand Down
103 changes: 103 additions & 0 deletions src/__tests__/phone-number-field-lite-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {render, screen} from '@testing-library/react';
import PhoneNumberFieldLite from '../phone-number-field-lite';
import {getMovistarSkin} from '../skins/movistar';
import ThemeContextProvider from '../theme-context-provider';
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import PhoneNumberField from '../phone-number-field';

test.each`
regionCode | number | expected | expectedRaw | expectedE164 | description
${'ZZ'} | ${'123456789012345'} | ${'123456789012345'} | ${'123456789012345'} | ${'123456789012345'} | ${'Unknown region'}
${'ES'} | ${'654834455'} | ${'654834455'} | ${'654 83 44 55'} | ${'+34654834455'} | ${'ES mobile'}
${'ES'} | ${'914-44/10 25'} | ${'914441025'} | ${'914 44 10 25'} | ${'+34914441025'} | ${'ES landline'}
${'ES'} | ${'6548344556'} | ${'6548344556'} | ${'6548344556'} | ${'+346548344556'} | ${'ES mobile too long'}
${'ES'} | ${'914-44/10 256'} | ${'9144410256'} | ${'9144410256'} | ${'+349144410256'} | ${'ES landline too long'}
${'ES'} | ${'+34 654 834 455'} | ${'+34654834455'} | ${'+34 654 83 44 55'} | ${'+34654834455'} | ${'ES E164 mobile'}
${'ES'} | ${'+34 914-44/10 25'} | ${'+34914441025'} | ${'+34 914 44 10 25'} | ${'+34914441025'} | ${'ES E164 landline'}
${'BR'} | ${'21987654321'} | ${'21987654321'} | ${'(21) 98765-4321'} | ${'+5521987654321'} | ${'BR mobile'}
${'BR'} | ${'219876543210'} | ${'219876543210'} | ${'219876543210'} | ${'+55219876543210'} | ${'BR mobile too long'}
${'BR'} | ${'2123456789'} | ${'2123456789'} | ${'(21) 2345-6789'} | ${'+552123456789'} | ${'BR landline'}
${'BR'} | ${'21234567890'} | ${'21234567890'} | ${'(21) 23456-7890'} | ${'+5521234567890'} | ${'BR landline long'}
${'BR'} | ${'212345678901'} | ${'212345678901'} | ${'212345678901'} | ${'+55212345678901'} | ${'BR landline too long'}
${'BR'} | ${'+5521987654321'} | ${'+5521987654321'} | ${'+55 21 98765-4321'} | ${'+5521987654321'} | ${'BR E164 mobile'}
${'BR'} | ${'+34654834455'} | ${'+34654834455'} | ${'+34 654 83 44 55'} | ${'+34654834455'} | ${'BR with ES E164'}
${'DE'} | ${'015789012345'} | ${'015789012345'} | ${'01578 9012345'} | ${'+4915789012345'} | ${'DE mobile 15'}
${'DE'} | ${'01601234567'} | ${'01601234567'} | ${'0160 1234567'} | ${'+491601234567'} | ${'DE mobile 16'}
${'DE'} | ${'01701234567'} | ${'01701234567'} | ${'0170 1234567'} | ${'+491701234567'} | ${'DE mobile 17'}
${'DE'} | ${'12345678901'} | ${'12345678901'} | ${'12345678901'} | ${'+4912345678901'} | ${'DE unknown'}
${'DE'} | ${'+4915789012345'} | ${'+4915789012345'} | ${'+49 1578 9012345'} | ${'+4915789012345'} | ${'DE E164 mobile'}
${'DE'} | ${'+49015789012345'} | ${'+49015789012345'} | ${'+49 015789012345'} | ${'+49015789012345'} | ${'DE E164 mobile wrong zero'}
${'GB'} | ${'07123456789'} | ${'07123456789'} | ${'07123 456789'} | ${'+447123456789'} | ${'GB mobile'}
${'GB'} | ${'071234567890'} | ${'071234567890'} | ${'071234567890'} | ${'+4471234567890'} | ${'GB mobile too long'}
${'GB'} | ${'+447123456789'} | ${'+447123456789'} | ${'+44 7123 456789'} | ${'+447123456789'} | ${'GB E164 mobile'}
${'GB'} | ${'+4407123456789'} | ${'+4407123456789'} | ${'+44 07123456789'} | ${'+4407123456789'} | ${'GB E164 mobile wrong zero'}
`(
'PhoneNumberFieldLite - $description - $number',
async ({regionCode, number, expected, expectedRaw, expectedE164}) => {
const onChangeValue = jest.fn();
const onChangeValueE164 = jest.fn();
const onChangeValueUsingLibphonenumber = jest.fn();

render(
<ThemeContextProvider
theme={{
skin: getMovistarSkin(),
i18n: {locale: 'es-ES', phoneNumberFormattingRegionCode: regionCode},
}}
>
<PhoneNumberFieldLite name="phone" label="Phone" onChangeValue={onChangeValue} />
<PhoneNumberFieldLite name="e164" label="Phone E164" onChangeValue={onChangeValueE164} e164 />
<PhoneNumberField
name="ref"
label="Reference"
onChangeValue={onChangeValueUsingLibphonenumber}
/>
</ThemeContextProvider>
);

const input = screen.getByLabelText('Phone');
const inputE164 = screen.getByLabelText('Phone E164');
const referenceInput = screen.getByLabelText('Reference');

await userEvent.type(input, number);
await userEvent.type(inputE164, number);
await userEvent.type(referenceInput, number);

expect(onChangeValue).toHaveBeenLastCalledWith(expected, expectedRaw);
expect(onChangeValueE164).toHaveBeenLastCalledWith(expectedE164, expectedRaw);

// We expect the same result as the libphonenumber version, except for the E164 format
if (!number.startsWith('+')) {
// This checks all the calls to onChangeValue (as you type)
expect(onChangeValue.mock.calls).toEqual(onChangeValueUsingLibphonenumber.mock.calls);
}
}
);

test('PhoneNumberFieldLite custom formatter', async () => {
const onChangeValue = jest.fn();

render(
<ThemeContextProvider
theme={{
skin: getMovistarSkin(),
i18n: {locale: 'es-ES', phoneNumberFormattingRegionCode: 'ES'},
}}
>
<PhoneNumberFieldLite
name="a"
label="Phone"
onChangeValue={onChangeValue}
format={(number) => {
return number.replace(/\D/g, '').split('').join('-');
}}
/>
</ThemeContextProvider>
);

const input = screen.getByLabelText('Phone');
await userEvent.type(input, '654834455');

expect(onChangeValue).toHaveBeenLastCalledWith('654834455', '6-5-4-8-3-4-4-5-5');
});
1 change: 0 additions & 1 deletion src/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export const useDisableBodyScroll = (disable: boolean): void => {
`top: ${-bodyScrollTop}px;`,
'left: 0px;',
'right: 0px;',
'bottom: 0px;',
'overscroll-behavior-y: contain;', // disable overscroll
].join('');
}
Expand Down
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export {TextFieldBase} from './text-field-base';
export {default as SearchField} from './search-field';
export {default as EmailField} from './email-field';
export {default as PhoneNumberField} from './phone-number-field';
export {default as PhoneNumberFieldLite, formatPhoneLite} from './phone-number-field-lite';
export {default as CreditCardNumberField} from './credit-card-number-field';
export {default as CreditCardExpirationField} from './credit-card-expiration-field';
export {default as CreditCardFields} from './credit-card-fields';
Expand Down
Loading

0 comments on commit aec3ec1

Please sign in to comment.