Skip to content

Commit

Permalink
Fix/v6 dropping TxVariants prop for Cards (#2428)
Browse files Browse the repository at this point in the history
* Removing txVariants static prop for card pms

* Rationalising how type and brand are sent through the Card, Bancontact, StoredCard & CustomCard components

* Cleaned up logs and removed commented out code

* merging v6 changes - again

* All Card comps now have consistent setting of type and brand props

* Fixed unit test
  • Loading branch information
sponglord authored Nov 23, 2023
1 parent 004f7fd commit d74c430
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 27 deletions.
7 changes: 6 additions & 1 deletion packages/lib/src/components/Card/Bancontact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ class BancontactElement extends CardElement {
formatProps(props: CardElementProps) {
return {
...super.formatProps(props),
type: 'bcmc', // Force type (only for the Dropin is type automatically set to 'bcmc') - this will bypass the regEx brand detection
/**
* Force type (only for the Dropin is type automatically set to 'bcmc')
* - this will bypass the regEx brand detection that SF normally tries to carry out when the first few digits are entered in the PAN
*/
type: TxVariants.bcmc,
brand: TxVariants.bcmc,
cvcPolicy: CVC_POLICY_HIDDEN
};
}
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/components/Card/Card.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('Card', () => {
test('should not require a billingAddress if it is a stored card', () => {
const card = new CardElement({ core: global.core, billingAddressRequired: true, storedPaymentMethodId: 'test' });
expect(card.props.billingAddressRequired).toBe(false);
expect(card.props.type).toEqual('card');
expect(card.props.type).toEqual('scheme');
});

test('should format countryCode to lowerCase', () => {
Expand Down
21 changes: 9 additions & 12 deletions packages/lib/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { TxVariants } from '../tx-variants';

export class CardElement extends UIElement<CardElementProps> {
public static type = TxVariants.scheme;
public static txVariants = [TxVariants.scheme, TxVariants.card];

private readonly clickToPayService: IClickToPayService | null;

Expand Down Expand Up @@ -66,7 +65,8 @@ export class CardElement extends UIElement<CardElementProps> {
// billingAddressRequired only available for non-stored cards
billingAddressRequired: props.storedPaymentMethodId ? false : props.billingAddressRequired,
// ...(props.brands && !props.groupTypes && { groupTypes: props.brands }),
type: props.type === 'scheme' ? 'card' : props.type,
/** props.brand will be specified in the case of a StoredCard or a Bancontact component, for a regular Card we default it to 'card' */
brand: props.brand ?? TxVariants.card,
countryCode: props.countryCode ? props.countryCode.toLowerCase() : null,
// Required for transition period (until configuration object becomes the norm)
// - if merchant has defined value directly in props, use this instead
Expand Down Expand Up @@ -98,11 +98,12 @@ export class CardElement extends UIElement<CardElementProps> {
*/
formatData(): CardElementData {
/**
* this.props.brand is never set for the generic card only for a 'dedicated' single-branded card e.g. bcmc
* this.state.selectedBrandValue will be set when /binLookup detects a single brand &/or when /binLookup detects a dual-branded card and
* the shopper makes a brand selection
* this.state.selectedBrandValue will be set when:
* - /binLookup detects a single brand,
* - when /binLookup detects a dual-branded card and the shopper makes a brand selection
* - or, in the case of a storedCard
*/
const cardBrand = this.state.selectedBrandValue || this.props.brand;
const cardBrand = this.state.selectedBrandValue;
const includeStorePaymentMethod = this.props.enableStoreDetails && typeof this.state.storePaymentMethod !== 'undefined';

return {
Expand Down Expand Up @@ -167,7 +168,7 @@ export class CardElement extends UIElement<CardElementProps> {
}

get icon() {
return this.props.icon ?? this.resources.getImage()(this.brand);
return this.props.icon ?? this.resources.getImage()(this.props.brand);
}

get brands(): { icon: any; name: string }[] {
Expand All @@ -182,10 +183,6 @@ export class CardElement extends UIElement<CardElementProps> {
return [];
}

get brand(): string {
return this.props.brand || this.props.type;
}

get displayName(): string {
if (this.props.storedPaymentMethodId) {
return `•••• ${this.props.lastFour}`;
Expand Down Expand Up @@ -219,7 +216,7 @@ export class CardElement extends UIElement<CardElementProps> {
payButton={this.payButton}
onBrand={this.onBrand}
onBinValue={this.onBinValue}
brand={this.brand}
brand={this.props.brand}
brandsIcons={this.brands}
isPayButtonPrimaryVariant={isCardPrimaryInput}
resources={this.resources}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const CardInput = (props: CardInputProps) => {
const [issuingCountryCode, setIssuingCountryCode] = useState<string>(null);

const [dualBrandSelectElements, setDualBrandSelectElements] = useState([]);
const [selectedBrandValue, setSelectedBrandValue] = useState('');
const [selectedBrandValue, setSelectedBrandValue] = useState(props.storedPaymentMethodId ? props.brand : ''); // If this is a storedCard comp initialise state with the storedCard's brand

const showBillingAddress = props.billingAddressMode !== AddressModeOptions.none && props.billingAddressRequired;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SocialSecurityMode } from '../../types';
import { AddressModeOptions } from './types';

export default {
type: 'card',
type: 'scheme',

setComponentRef: () => {},

Expand Down
10 changes: 5 additions & 5 deletions packages/lib/src/components/Card/components/CardInput/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export const extractPropsForSFP = (props: CardInputProps) => {
keypadFix: props.keypadFix,
legacyInputMode: props.legacyInputMode,
loadingContext: props.loadingContext,
maskSecurityCode: props.maskSecurityCode,
minimumExpiryDate: props.minimumExpiryDate,
onAdditionalSFConfig: props.onAdditionalSFConfig,
onAdditionalSFRemoved: props.onAdditionalSFRemoved,
Expand All @@ -158,12 +159,11 @@ export const extractPropsForSFP = (props: CardInputProps) => {
onError: props.onError,
onFieldValid: props.onFieldValid,
onLoad: props.onLoad,
showWarnings: props.showWarnings,
trimTrailingSeparator: props.trimTrailingSeparator,
resources: props.resources,
maskSecurityCode: props.maskSecurityCode,
placeholders: props.placeholders,
showContextualElement: props.showContextualElement
resources: props.resources,
showContextualElement: props.showContextualElement,
showWarnings: props.showWarnings,
trimTrailingSeparator: props.trimTrailingSeparator
} as SFPProps; // Can't set as return type on fn or it will complain about missing, mandatory, props
};

Expand Down
7 changes: 4 additions & 3 deletions packages/lib/src/components/CustomCard/CustomCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ type CustomCardProps = Omit<

export class CustomCard extends UIElement<CustomCardProps> {
public static type = TxVariants.customCard;
public static txVariants = [TxVariants.customCard, TxVariants.card];

public static analyticsType = 'custom-scheme';

Expand All @@ -50,15 +49,16 @@ export class CustomCard extends UIElement<CustomCardProps> {
formatProps(props: CustomCardProps) {
return {
...props,
type: props.type === 'scheme' || props.type === 'securedfields' ? 'card' : props.type
type: TxVariants.customCard,
brand: TxVariants.card
};
}

/**
* Formats the component data output
*/
formatData() {
const sfBrand = this.state.selectedBrandValue || this.props.brand;
const sfBrand = this.state.selectedBrandValue;
return {
paymentMethod: {
type: 'scheme',
Expand Down Expand Up @@ -137,6 +137,7 @@ export class CustomCard extends UIElement<CustomCardProps> {
onBinValue={this.onBinValue}
implementationType={'custom'}
resources={this.resources}
brand={this.props.brand}
/>
</CoreProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Placeholders } from '../../Card/components/CardInput/types';

interface SecuredFieldsProps {
autoFocus?: boolean;
brand?: string;
brands?: string[];
brandsConfiguration?: CardBrandsConfiguration;
clientKey?: string;
Expand Down Expand Up @@ -124,7 +125,16 @@ function CustomCardInput(props: SecuredFieldsProps) {
/**
* RENDER
*/
return <SecuredFieldsProvider ref={sfp} {...extractPropsForSFP(props)} onChange={handleSecuredFieldsChange} render={() => null} />;
// prettier-ignore
return (
<SecuredFieldsProvider
ref={sfp}
{...extractPropsForSFP(props)}
type={props.brand}
onChange={handleSecuredFieldsChange}
render={() => null}
/>
);
}

CustomCardInput.defaultProps = defaultProps;
Expand Down Expand Up @@ -161,7 +171,6 @@ const extractPropsForSFP = (props: SecuredFieldsProps) => {
showWarnings: props.showWarnings,
styles: props.styles,
trimTrailingSeparator: props.trimTrailingSeparator,
type: props.type,
resources: props.resources,
maskSecurityCode: props.maskSecurityCode,
placeholders: props.placeholders
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default parent => {
path: `v3/bin/binLookup?token=${parent.props.clientKey}`
},
{
type: parent.props.type,
type: parent.props.brand,
supportedBrands: parent.props.brands || DEFAULT_CARD_GROUP_TYPES,
encryptedBin: callbackObj.encryptedBin,
requestId: callbackObj.uuid // Pass id of request
Expand Down

0 comments on commit d74c430

Please sign in to comment.