Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
59bfc2f
Add client-side logic to fetch promotional details from server
dmallory42 Nov 11, 2025
af532b3
Update woopmnt-5496-add-logic-to-woopayments-client-to-fetch-promotio…
dmallory42 Nov 11, 2025
135342c
Fix naming conventions and caching in promotions controller
dmallory42 Nov 11, 2025
99537d5
Add promotions controller to test bootstrap
dmallory42 Nov 11, 2025
ea69288
Add promotions route to Request validation list
dmallory42 Nov 11, 2025
ddc3d29
Fix promotions selectors to handle full Redux state
dmallory42 Nov 11, 2025
9341311
Move activatePromotion and dismissPromotion from resolvers to actions
dmallory42 Nov 11, 2025
05e1bec
Update promotions API response to support variations
dmallory42 Nov 14, 2025
68c290d
Rename API endpoint from promotions to payment-method-promotions
dmallory42 Nov 14, 2025
8e62e1c
Update to reflect structural changes to the API response.
dmallory42 Nov 14, 2025
41bd8d4
Add footnote support to promotions API and cleanup testing files
dmallory42 Nov 19, 2025
0d42bd7
Build Klarna promotion Spotlight component (#11139)
dmallory42 Nov 21, 2025
20527e8
Display spotlight promotions on WooPayments and WC payment settings p…
dmallory42 Nov 21, 2025
797ca7e
Merge remote-tracking branch 'origin/develop' into add/payment-method…
dmallory42 Nov 25, 2025
3993a9b
Add dismissal and variation support for spotlight promotions (#11149)
dmallory42 Nov 25, 2025
cde403d
Merge branch 'develop' into add/payment-method-promotions
vladolaru Nov 26, 2025
b67d3e8
Add analytics tracking for payment method promotions (#11161)
dmallory42 Nov 27, 2025
e7c4eaf
Payment method promotions adjustments (#11162)
vladolaru Nov 27, 2025
bcd5f66
Merge branch 'develop' into add/payment-method-promotions
vladolaru Nov 27, 2025
d0c743f
Add promotional discount badges to payment methods in settings (#11166)
mordeth Nov 28, 2025
6deef64
Merge branch 'develop' into add/payment-method-promotions
vladolaru Nov 28, 2025
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
2 changes: 2 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,5 @@ npm run i18n:pot # Generate translations
- Test files mirror source structure
- PHP tests require Docker - ensure it's running before executing tests
- Use `npm run test:php` to run all tests or edit the command to pass PHPUnit filters
- When pushing, always push only the current branch: `git push origin HEAD` (not `git push` which tries to push all configured branches)
- When pulling, always pull only the current branch: `git pull origin $(git branch --show-current)` or `git pull --rebase origin HEAD`
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ project.properties
.sublimelinterrc
.cursor/
**/.claude/**/*.local.*
.claude/local/
.zed/
.phpactor.json

Expand Down
29 changes: 29 additions & 0 deletions assets/images/illustrations/klarna-promotion-spotlight.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions changelog/add-WOOPMNT-5460-discount-badges-to-payment-methods
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add discount badges to payment methods with active promotions in settings.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: Add generic Spotlight component for promotional announcements


4 changes: 4 additions & 0 deletions changelog/woopmnt-5463-display-spotlight-promotions
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: add

Display spotlight promotions on WooPayments pages and WooCommerce payment settings.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add client-side logic to fetch promotional details from server
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PromotionalBadge renders correctly with all props 1`] = `
<div>
<span
class="chip chip-primary wcpay-promotional-badge"
>
30% off fees through Dec 31, 2026
<button
class="wcpay-tooltip__content-wrapper wcpay-tooltip--click__content-wrapper"
type="button"
>
<div
class="wcpay-tooltip__content-wrapper"
>
<div
aria-label="View promotion details"
role="button"
tabindex="0"
>
<svg
class="gridicon gridicons-info-outline"
height="16"
viewBox="0 0 24 24"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M13 9h-2V7h2v2zm0 2h-2v6h2v-6zm-1-7c-4.411 0-8 3.589-8 8s3.589 8 8 8 8-3.589 8-8-3.589-8-8-8m0-2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2z"
/>
</g>
</svg>
</div>
</div>
</button>
</span>
</div>
`;
120 changes: 120 additions & 0 deletions client/components/promotional-badge/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/** @format */

/**
* External dependencies
*/
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';

/**
* Internal dependencies
*/
import PromotionalBadge from '../';

describe( 'PromotionalBadge', () => {
test( 'renders the badge with message', () => {
render(
<PromotionalBadge
message="50% off fees"
tooltip="You are getting 50% off on processing fees."
/>
);

expect( screen.getByText( '50% off fees' ) ).toBeInTheDocument();
} );

test( 'renders with success type by default', () => {
const { container } = render(
<PromotionalBadge
message="25% off fees"
tooltip="Discount details"
/>
);

const badge = container.querySelector( '.wcpay-promotional-badge' );
expect( badge ).toHaveClass( 'chip-success' );
} );

test( 'renders with custom chip type', () => {
const { container } = render(
<PromotionalBadge
message="Limited offer"
tooltip="Discount details"
type="warning"
/>
);

const badge = container.querySelector( '.wcpay-promotional-badge' );
expect( badge ).toHaveClass( 'chip-warning' );
} );

test( 'renders the info icon button', () => {
render(
<PromotionalBadge
message="50% off fees"
tooltip="Tooltip content"
tooltipLabel="Discount details"
/>
);

const tooltipButton = screen.getByRole( 'button', {
name: /discount details/i,
} );
expect( tooltipButton ).toBeInTheDocument();
} );

test( 'shows tooltip content when clicking the info icon', () => {
render(
<PromotionalBadge
message="50% off fees"
tooltip="You are getting 50% off on processing fees."
tooltipLabel="Discount details"
/>
);

const tooltipButton = screen.getByRole( 'button', {
name: /discount details/i,
} );
fireEvent.click( tooltipButton );

expect(
screen.getByText( 'You are getting 50% off on processing fees.' )
).toBeInTheDocument();
} );

test( 'uses default tooltip label when not provided', () => {
render(
<PromotionalBadge
message="50% off fees"
tooltip="Tooltip content"
/>
);

const tooltipButton = screen.getByRole( 'button', {
name: /more information/i,
} );
expect( tooltipButton ).toBeInTheDocument();
} );

test( 'applies chip base class', () => {
const { container } = render(
<PromotionalBadge message="Test badge" tooltip="Test tooltip" />
);

const badge = container.querySelector( '.wcpay-promotional-badge' );
expect( badge ).toHaveClass( 'chip' );
} );

test( 'renders correctly with all props', () => {
const { container } = render(
<PromotionalBadge
message="30% off fees through Dec 31, 2026"
tooltip="You are getting 30% off on processing fees for the first $1,000 of total payment volume or through Dec 31, 2026."
type="primary"
tooltipLabel="View promotion details"
/>
);

expect( container ).toMatchSnapshot();
} );
} );
53 changes: 53 additions & 0 deletions client/components/promotional-badge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/** @format */

/**
* External dependencies
*/
import React from 'react';
import clsx from 'clsx';
import InfoOutlineIcon from 'gridicons/dist/info-outline';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { ChipType } from 'wcpay/components/chip';
import { ClickTooltip } from 'wcpay/components/tooltip';
import './style.scss';

interface PromotionalBadgeProps {
/** The badge text displayed in the chip */
message: string;
/** The tooltip content shown when clicking the info icon */
tooltip: string;
/** The chip type/color (defaults to "success") */
type?: ChipType;
/** Accessible label for the tooltip button */
tooltipLabel?: string;
}

const PromotionalBadge: React.FC< PromotionalBadgeProps > = ( {
message,
tooltip,
type = 'success',
tooltipLabel = __( 'More information', 'woocommerce-payments' ),
} ) => {
const classNames = clsx(
'chip',
`chip-${ type }`,
'wcpay-promotional-badge'
);

return (
<span className={ classNames }>
{ message }
<ClickTooltip
buttonIcon={ <InfoOutlineIcon /> }
buttonLabel={ tooltipLabel }
content={ tooltip }
/>
</span>
);
};

export default PromotionalBadge;
21 changes: 21 additions & 0 deletions client/components/promotional-badge/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @format */

.wcpay-promotional-badge {
display: inline-flex;
align-items: center;
gap: 4px;

.wcpay-tooltip__content-wrapper {
display: inline-flex;
align-items: center;
background: none;
border: none;
padding: 0;
margin: 0;
cursor: pointer;

> div {
margin-right: 0;
}
}
}
Loading
Loading