Skip to content

Commit

Permalink
Add Transaction Details notice when a dispute has staged evidence (#7139
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Jinksi authored Sep 7, 2023
1 parent ef54b3b commit 12ac12d
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: add
Comment: Behind feature flag: add staged dispute notice to Transaction Details screen


30 changes: 24 additions & 6 deletions client/payment-details/dispute-details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
*/
import React from 'react';
import moment from 'moment';
import { __ } from '@wordpress/i18n';
import { Card, CardBody } from '@wordpress/components';
import { edit } from '@wordpress/icons';

/**
* Internal dependencies
*/
import type { Dispute } from 'wcpay/types/disputes';
import { Card, CardBody } from '@wordpress/components';
import './style.scss';
import DisputeNotice from './dispute-notice';
import { isAwaitingResponse } from 'wcpay/disputes/utils';
import InlineNotice from 'components/inline-notice';
import './style.scss';

interface DisputeDetailsProps {
dispute: Dispute;
Expand All @@ -22,17 +26,31 @@ const DisputeDetails: React.FC< DisputeDetailsProps > = ( { dispute } ) => {
const now = moment();
const dueBy = moment.unix( dispute.evidence_details?.due_by ?? 0 );
const countdownDays = Math.floor( dueBy.diff( now, 'days', true ) );
const hasStagedEvidence = dispute.evidence_details?.has_evidence;

return (
<div className="transaction-details-dispute-details-wrapper">
<Card>
<CardBody className="transaction-details-dispute-details-body">
{ isAwaitingResponse( dispute.status ) &&
countdownDays >= 0 && (
<DisputeNotice
dispute={ dispute }
urgent={ countdownDays <= 2 }
/>
<>
<DisputeNotice
dispute={ dispute }
urgent={ countdownDays <= 2 }
/>
{ hasStagedEvidence && (
<InlineNotice
icon={ edit }
isDismissible={ false }
>
{ __(
`You initiated a dispute a challenge to this dispute. Click 'Continue with challenge' to proceed with your drafted response.`,
'woocommerce-payments'
) }
</InlineNotice>
) }
</>
) }
</CardBody>
</Card>
Expand Down
8 changes: 8 additions & 0 deletions client/payment-details/dispute-details/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,13 @@

.transaction-details-dispute-details-body {
padding: $grid-unit-20;

.wcpay-inline-notice.components-notice {
margin: 0 0 10px 0;

&:last-child {
margin-bottom: 24px;
}
}
}
}
171 changes: 171 additions & 0 deletions client/payment-details/dispute-details/test/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/** @format */
/**
* External dependencies
*/
import { render, screen } from '@testing-library/react';
import React from 'react';

/**
* Internal dependencies
*/
import type { Dispute } from 'wcpay/types/disputes';
import type { Charge } from 'wcpay/types/charges';
import DisputeDetails from '..';

declare const global: {
wcSettings: {
locale: {
siteLocale: string;
};
};
wcpaySettings: {
isSubscriptionsActive: boolean;
zeroDecimalCurrencies: string[];
currencyData: Record< string, any >;
connect: {
country: string;
};
featureFlags: {
isAuthAndCaptureEnabled: boolean;
};
};
};

global.wcpaySettings = {
isSubscriptionsActive: false,
zeroDecimalCurrencies: [],
connect: {
country: 'US',
},
featureFlags: {
isAuthAndCaptureEnabled: true,
},
currencyData: {
US: {
code: 'USD',
symbol: '$',
symbolPosition: 'left',
thousandSeparator: ',',
decimalSeparator: '.',
precision: 2,
},
},
};

interface ChargeWithDisputeRequired extends Charge {
dispute: Dispute;
}

const getBaseCharge = (): ChargeWithDisputeRequired =>
( {
id: 'ch_38jdHA39KKA',
/* Stripe data comes in seconds, instead of the default Date milliseconds */
created: Date.parse( 'Sep 19, 2019, 5:24 pm' ) / 1000,
amount: 2000,
amount_refunded: 0,
application_fee_amount: 70,
disputed: true,
dispute: {
id: 'dp_1',
amount: 6800,
charge: 'ch_38jdHA39KKA',
order: null,
balance_transactions: [
{
amount: -2000,
currency: 'usd',
fee: 1500,
},
],
created: 1693453017,
currency: 'usd',
evidence: {
billing_address: '123 test address',
customer_email_address: '[email protected]',
customer_name: 'Test customer',
shipping_address: '123 test address',
},
evidence_details: {
due_by: 1694303999,
has_evidence: false,
past_due: false,
submission_count: 0,
},
// issuer_evidence: null,
metadata: [],
payment_intent: 'pi_1',
reason: 'fraudulent',
status: 'needs_response',
} as Dispute,
currency: 'usd',
type: 'charge',
status: 'succeeded',
paid: true,
captured: true,
balance_transaction: {
amount: 2000,
currency: 'usd',
fee: 70,
},
refunds: {
data: [],
},
order: {
number: 45981,
url: 'https://somerandomorderurl.com/?edit_order=45981',
},
billing_details: {
name: 'Customer name',
},
payment_method_details: {
card: {
brand: 'visa',
last4: '4242',
},
type: 'card',
},
outcome: {
risk_level: 'normal',
},
} as any );

describe( 'DisputeDetails', () => {
test( 'correctly renders dispute details', () => {
const charge = getBaseCharge();
render( <DisputeDetails dispute={ charge.dispute } /> );

screen.getByText(
/The cardholder claims this is an unauthorized transaction/,
{ ignore: '.a11y-speak-region' }
);
// Don't render the staged evidence message
expect(
screen.queryByText(
/You initiated a dispute a challenge to this dispute/,
{ ignore: '.a11y-speak-region' }
)
).toBeNull();
} );

test( 'correctly renders dispute details for a dispute with staged evidence', () => {
const charge = getBaseCharge();
charge.dispute.evidence_details = {
has_evidence: true,
due_by: 1694303999,
past_due: false,
submission_count: 0,
};

render( <DisputeDetails dispute={ charge.dispute } /> );

screen.getByText(
/The cardholder claims this is an unauthorized transaction/,
{ ignore: '.a11y-speak-region' }
);
// Render the staged evidence message
screen.getByText(
/You initiated a dispute a challenge to this dispute/,
{ ignore: '.a11y-speak-region' }
);
} );
} );
15 changes: 14 additions & 1 deletion client/types/disputes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ interface Evidence {
}

interface EvidenceDetails {
/**
* Whether evidence has been staged for this dispute.
*/
has_evidence: boolean;
/**
* Date by which evidence must be submitted in order to successfully challenge dispute.
*/
due_by: number;
/**
* Whether the last evidence submission was submitted past the due date. Defaults to false if no evidence submissions have occurred. If true, then delivery of the latest evidence is not guaranteed.
*/
past_due: boolean;
/**
* The number of times evidence has been submitted. Typically, the merchant may only submit evidence once.
*/
submission_count: number;
}

Expand Down Expand Up @@ -51,7 +64,7 @@ export interface Dispute {
evidence: Evidence;
fileSize?: Record< string, number >;
reason: DisputeReason;
charge: Charge;
charge: Charge | string;
amount: number;
currency: string;
created: number;
Expand Down

0 comments on commit 12ac12d

Please sign in to comment.