Skip to content

Commit a6928ba

Browse files
@W-19143871 Ignore Subscribe button on the email footer component when EnableConsentWithMarketingCloud flag is enabled
1 parent e518f4d commit a6928ba

File tree

5 files changed

+153
-2
lines changed

5 files changed

+153
-2
lines changed

packages/template-retail-react-app/app/components/subscription/hooks/use-email-subscription.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export const useEmailSubscription = ({tag} = {}) => {
5151
const {
5252
refetch: fetchSubscriptions,
5353
updateSubscriptions,
54-
isUpdating
54+
isUpdating,
55+
isFeatureEnabled
5556
} = useMarketingConsent({
5657
tags,
5758
enabled: false
@@ -94,6 +95,10 @@ export const useEmailSubscription = ({tag} = {}) => {
9495
return
9596
}
9697

98+
if (!isFeatureEnabled) {
99+
return
100+
}
101+
97102
try {
98103
setMessage(null)
99104

@@ -143,7 +148,7 @@ export const useEmailSubscription = ({tag} = {}) => {
143148
setMessage(messages.error.generic_error)
144149
setMessageType('error')
145150
}
146-
}, [email, tags, fetchSubscriptions, updateSubscriptions, messages])
151+
}, [email, tags, isFeatureEnabled, fetchSubscriptions, updateSubscriptions, messages])
147152

148153
return {
149154
state: {

packages/template-retail-react-app/app/components/subscription/hooks/use-email-subscription.test.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ describe('useEmailSubscription', () => {
8282
useMarketingConsent.mockReturnValue({
8383
data: {data: mockMatchingSubscriptions},
8484
isLoading: false,
85+
isFeatureEnabled: true,
8586
refetch: jest.fn().mockResolvedValue({data: {data: mockMatchingSubscriptions}}),
8687
updateSubscriptions: mockUpdateSubscriptions,
8788
isUpdating: false,
@@ -252,6 +253,7 @@ describe('useEmailSubscription', () => {
252253

253254
useMarketingConsent.mockReturnValue({
254255
data: {data: []},
256+
isFeatureEnabled: true,
255257
refetch: mockRefetch,
256258
updateSubscriptions: mockUpdateSubscriptions,
257259
isUpdating: false
@@ -281,6 +283,7 @@ describe('useEmailSubscription', () => {
281283

282284
useMarketingConsent.mockReturnValue({
283285
data: {data: []},
286+
isFeatureEnabled: true,
284287
refetch: mockRefetch,
285288
updateSubscriptions: mockUpdateSubscriptions,
286289
isUpdating: false
@@ -407,6 +410,7 @@ describe('useEmailSubscription', () => {
407410

408411
useMarketingConsent.mockReturnValue({
409412
data: {data: [mockMatchingSubscriptions[0]]},
413+
isFeatureEnabled: true,
410414
refetch: mockRefetch,
411415
updateSubscriptions: mockUpdateSubscriptions,
412416
isUpdating: false
@@ -576,6 +580,53 @@ describe('useEmailSubscription', () => {
576580
})
577581
})
578582

583+
describe('submit action - feature disabled (no-op)', () => {
584+
beforeEach(() => {
585+
useMarketingConsent.mockReturnValue({
586+
data: {data: mockMatchingSubscriptions},
587+
isLoading: false,
588+
isFeatureEnabled: false,
589+
refetch: jest.fn().mockResolvedValue({data: {data: mockMatchingSubscriptions}}),
590+
updateSubscriptions: mockUpdateSubscriptions,
591+
isUpdating: false,
592+
getSubscriptionsByTagAndChannel: mockGetSubscriptionsByTagAndChannel
593+
})
594+
})
595+
596+
test('does nothing when feature is disabled', async () => {
597+
const {result} = renderHook(() => useEmailSubscription({tag: 'email_capture'}), {
598+
wrapper: createWrapper()
599+
})
600+
601+
act(() => {
602+
result.current.actions.setEmail('test@example.com')
603+
})
604+
605+
await act(async () => {
606+
await result.current.actions.submit()
607+
})
608+
609+
expect(result.current.state.feedback.message).toBeNull()
610+
expect(result.current.state.feedback.type).toBe('success')
611+
expect(result.current.state.email).toBe('test@example.com')
612+
expect(mockUpdateSubscriptions).not.toHaveBeenCalled()
613+
})
614+
615+
test('still validates email when feature is disabled', async () => {
616+
const {result} = renderHook(() => useEmailSubscription({tag: 'email_capture'}), {
617+
wrapper: createWrapper()
618+
})
619+
620+
await act(async () => {
621+
await result.current.actions.submit()
622+
})
623+
624+
expect(result.current.state.feedback.type).toBe('error')
625+
expect(result.current.state.feedback.message).toBe('Enter a valid email address.')
626+
expect(mockUpdateSubscriptions).not.toHaveBeenCalled()
627+
})
628+
})
629+
579630
describe('Loading states', () => {
580631
test('reflects isUpdating state from useMarketingConsent', () => {
581632
useMarketingConsent.mockReturnValue({
@@ -619,6 +670,7 @@ describe('useEmailSubscription', () => {
619670

620671
useMarketingConsent.mockReturnValue({
621672
data: {data: mockCheckoutSubscriptions},
673+
isFeatureEnabled: true,
622674
refetch: mockRefetch,
623675
updateSubscriptions: mockUpdateSubscriptions,
624676
isUpdating: false
@@ -682,6 +734,7 @@ describe('useEmailSubscription', () => {
682734

683735
useMarketingConsent.mockReturnValue({
684736
data: {data: mockApiFormatSubscriptions},
737+
isFeatureEnabled: true,
685738
refetch: mockRefetch,
686739
updateSubscriptions: mockUpdateSubscriptions,
687740
isUpdating: false
@@ -736,6 +789,7 @@ describe('useEmailSubscription', () => {
736789

737790
useMarketingConsent.mockReturnValue({
738791
data: {data: mockMultipleTagsSubscriptions},
792+
isFeatureEnabled: true,
739793
refetch: mockRefetch,
740794
updateSubscriptions: mockUpdateSubscriptions,
741795
isUpdating: false
@@ -794,6 +848,7 @@ describe('useEmailSubscription', () => {
794848

795849
useMarketingConsent.mockReturnValue({
796850
data: {data: mockMixedChannelSubscriptions},
851+
isFeatureEnabled: true,
797852
refetch: mockRefetch,
798853
updateSubscriptions: mockUpdateSubscriptions,
799854
isUpdating: false
@@ -849,6 +904,7 @@ describe('useEmailSubscription', () => {
849904
useMarketingConsent.mockReturnValue({
850905
data: undefined,
851906
isLoading: false,
907+
isFeatureEnabled: true,
852908
refetch: mockRefetch,
853909
updateSubscriptions: mockUpdateSubscriptions,
854910
isUpdating: false,

packages/template-retail-react-app/app/constants/marketing-consent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77

8+
// Shopper Configurations feature flag for marketing consent
9+
export const ENABLE_CONSENT_WITH_MARKETING_CLOUD = 'EnableConsentWithMarketingCloud'
10+
811
// Marketing consent status constants
912
export const CONSENT_STATUS = {
1013
OPT_IN: 'opt_in',

packages/template-retail-react-app/app/hooks/use-marketing-consent.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
import {
99
useSubscriptions,
10+
useConfigurations,
1011
useShopperConsentsMutation,
1112
ShopperConsentsMutations
1213
} from '@salesforce/commerce-sdk-react'
1314
import {useEffect} from 'react'
15+
import {ENABLE_CONSENT_WITH_MARKETING_CLOUD} from '@salesforce/retail-react-app/app/constants/marketing-consent'
1416

1517
/**
1618
* A hook for managing customer marketing consent subscriptions.
@@ -75,6 +77,13 @@ import {useEffect} from 'react'
7577
* const hasEmailChannel = hasChannel('marketing-email', 'email')
7678
*/
7779
export const useMarketingConsent = ({enabled = true, tags = [], expand} = {}) => {
80+
// Check if the feature is enabled via Shopper Configurations
81+
const {data: configurations} = useConfigurations()
82+
const isFeatureEnabled =
83+
configurations?.configurations?.find(
84+
(config) => config.id === ENABLE_CONSENT_WITH_MARKETING_CLOUD
85+
)?.value === true
86+
7887
// Query hook to get current subscriptions
7988
const subscriptionsQuery = useSubscriptions(
8089
{
@@ -248,6 +257,9 @@ export const useMarketingConsent = ({enabled = true, tags = [], expand} = {}) =>
248257
}
249258

250259
return {
260+
// Feature flag from Shopper Configurations
261+
isFeatureEnabled,
262+
251263
// Query data and status
252264
data: subscriptionsQuery.data,
253265
isLoading: subscriptionsQuery.isLoading,

packages/template-retail-react-app/app/hooks/use-marketing-consent.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {renderHook} from '@testing-library/react'
99
import {useMarketingConsent} from '@salesforce/retail-react-app/app/hooks/use-marketing-consent'
1010
import {
1111
useSubscriptions,
12+
useConfigurations,
1213
useShopperConsentsMutation,
1314
ShopperConsentsMutations
1415
} from '@salesforce/commerce-sdk-react'
@@ -19,6 +20,7 @@ jest.mock('@salesforce/commerce-sdk-react', () => {
1920
return {
2021
...originalModule,
2122
useSubscriptions: jest.fn(),
23+
useConfigurations: jest.fn(),
2224
useShopperConsentsMutation: jest.fn()
2325
}
2426
})
@@ -115,6 +117,26 @@ const mockUseMutationResult = {
115117
error: null
116118
}
117119

120+
const mockConfigurationsEnabled = {
121+
configurations: [
122+
{
123+
configurationType: 'globalConfiguration',
124+
id: 'EnableConsentWithMarketingCloud',
125+
value: true
126+
}
127+
]
128+
}
129+
130+
const mockConfigurationsDisabled = {
131+
configurations: [
132+
{
133+
configurationType: 'globalConfiguration',
134+
id: 'EnableConsentWithMarketingCloud',
135+
value: false
136+
}
137+
]
138+
}
139+
118140
describe('useMarketingConsent', () => {
119141
beforeEach(() => {
120142
jest.clearAllMocks()
@@ -123,6 +145,9 @@ describe('useMarketingConsent', () => {
123145
...mockUseQueryResult,
124146
data: mockSubscriptionsData
125147
})
148+
useConfigurations.mockReturnValue({
149+
data: mockConfigurationsEnabled
150+
})
126151
useShopperConsentsMutation.mockImplementation(() => {
127152
return mockUseMutationResult
128153
})
@@ -974,4 +999,54 @@ describe('useMarketingConsent', () => {
974999
expect(result.current.isUpdateSuccess).toBe(true)
9751000
})
9761001
})
1002+
1003+
describe('Feature flag (EnableConsentWithMarketingCloud)', () => {
1004+
test('isFeatureEnabled is true when configuration value is true', () => {
1005+
const {result} = renderHook(() => useMarketingConsent())
1006+
1007+
expect(result.current.isFeatureEnabled).toBe(true)
1008+
})
1009+
1010+
test('isFeatureEnabled is false when configuration value is false', () => {
1011+
useConfigurations.mockReturnValue({
1012+
data: mockConfigurationsDisabled
1013+
})
1014+
1015+
const {result} = renderHook(() => useMarketingConsent())
1016+
1017+
expect(result.current.isFeatureEnabled).toBe(false)
1018+
})
1019+
1020+
test('isFeatureEnabled is false when configuration is missing', () => {
1021+
useConfigurations.mockReturnValue({
1022+
data: {configurations: []}
1023+
})
1024+
1025+
const {result} = renderHook(() => useMarketingConsent())
1026+
1027+
expect(result.current.isFeatureEnabled).toBe(false)
1028+
})
1029+
1030+
test('isFeatureEnabled is false when configurations data is undefined', () => {
1031+
useConfigurations.mockReturnValue({data: undefined})
1032+
1033+
const {result} = renderHook(() => useMarketingConsent())
1034+
1035+
expect(result.current.isFeatureEnabled).toBe(false)
1036+
})
1037+
1038+
test('isFeatureEnabled is false when value is string "true" (must be boolean)', () => {
1039+
useConfigurations.mockReturnValue({
1040+
data: {
1041+
configurations: [
1042+
{id: 'EnableConsentWithMarketingCloud', value: 'true'}
1043+
]
1044+
}
1045+
})
1046+
1047+
const {result} = renderHook(() => useMarketingConsent())
1048+
1049+
expect(result.current.isFeatureEnabled).toBe(false)
1050+
})
1051+
})
9771052
})

0 commit comments

Comments
 (0)