@capillarytech/creatives-library 8.0.309 → 8.0.310

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/constants/unified.js +1 -5
  2. package/initialState.js +2 -0
  3. package/package.json +1 -1
  4. package/services/api.js +0 -17
  5. package/services/tests/api.test.js +0 -85
  6. package/utils/common.js +8 -5
  7. package/utils/commonUtils.js +93 -46
  8. package/utils/tagValidations.js +223 -83
  9. package/utils/tests/commonUtil.test.js +124 -316
  10. package/utils/tests/tagValidations.test.js +358 -441
  11. package/v2Components/CommonTestAndPreview/SendTestMessage.js +49 -78
  12. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +34 -134
  13. package/v2Components/CommonTestAndPreview/actions.js +0 -10
  14. package/v2Components/CommonTestAndPreview/constants.js +1 -15
  15. package/v2Components/CommonTestAndPreview/index.js +19 -80
  16. package/v2Components/CommonTestAndPreview/messages.js +0 -94
  17. package/v2Components/CommonTestAndPreview/reducer.js +0 -10
  18. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +0 -53
  19. package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -31
  20. package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -36
  21. package/v2Components/CommonTestAndPreview/tests/reducer.test.js +0 -71
  22. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +0 -377
  23. package/v2Components/CommonTestAndPreview/tests/selectors.test.js +0 -17
  24. package/v2Components/ErrorInfoNote/index.js +5 -2
  25. package/v2Components/FormBuilder/index.js +203 -137
  26. package/v2Components/FormBuilder/messages.js +8 -0
  27. package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
  28. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
  30. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
  31. package/v2Containers/Cap/mockData.js +14 -0
  32. package/v2Containers/Cap/reducer.js +55 -3
  33. package/v2Containers/Cap/tests/reducer.test.js +102 -0
  34. package/v2Containers/CreativesContainer/SlideBoxContent.js +1 -5
  35. package/v2Containers/CreativesContainer/SlideBoxFooter.js +5 -13
  36. package/v2Containers/CreativesContainer/constants.js +0 -6
  37. package/v2Containers/CreativesContainer/index.js +7 -47
  38. package/v2Containers/Email/index.js +5 -1
  39. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +70 -23
  40. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +120 -20
  41. package/v2Containers/FTP/index.js +51 -2
  42. package/v2Containers/FTP/messages.js +4 -0
  43. package/v2Containers/InApp/index.js +107 -35
  44. package/v2Containers/InApp/tests/index.test.js +6 -17
  45. package/v2Containers/InappAdvance/index.js +112 -4
  46. package/v2Containers/InappAdvance/tests/index.test.js +0 -2
  47. package/v2Containers/Line/Container/Text/index.js +1 -0
  48. package/v2Containers/MobilePush/Create/index.js +19 -59
  49. package/v2Containers/MobilePush/Edit/index.js +20 -48
  50. package/v2Containers/MobilePushNew/index.js +32 -12
  51. package/v2Containers/MobilepushWrapper/index.js +1 -3
  52. package/v2Containers/Rcs/index.js +37 -12
  53. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1276 -1408
  54. package/v2Containers/Sms/Create/index.js +3 -39
  55. package/v2Containers/Sms/Create/messages.js +0 -4
  56. package/v2Containers/Sms/Edit/index.js +3 -35
  57. package/v2Containers/Sms/commonMethods.js +6 -3
  58. package/v2Containers/SmsTrai/Edit/index.js +47 -11
  59. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +294 -327
  60. package/v2Containers/SmsWrapper/index.js +0 -2
  61. package/v2Containers/TemplatesV2/index.js +13 -28
  62. package/v2Containers/Viber/index.js +1 -0
  63. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  64. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  65. package/v2Containers/WebPush/Create/index.js +2 -2
  66. package/v2Containers/WebPush/Create/utils/validation.js +8 -17
  67. package/v2Containers/WebPush/Create/utils/validation.test.js +24 -44
  68. package/v2Containers/Whatsapp/index.js +17 -9
  69. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +4872 -5246
  70. package/v2Containers/Zalo/index.js +11 -3
  71. package/v2Components/CommonTestAndPreview/AddTestCustomer.js +0 -42
  72. package/v2Components/CommonTestAndPreview/CustomerCreationModal.js +0 -284
  73. package/v2Components/CommonTestAndPreview/ExistingCustomerModal.js +0 -72
  74. package/v2Components/CommonTestAndPreview/tests/AddTestCustomer.test.js +0 -66
  75. package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +0 -657
  76. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +0 -172
  77. package/v2Components/CommonTestAndPreview/tests/CustomerCreationModal.test.js +0 -466
  78. package/v2Components/CommonTestAndPreview/tests/ExistingCustomerModal.test.js +0 -114
  79. package/v2Containers/Sms/tests/commonMethods.test.js +0 -122
@@ -270,15 +270,23 @@ export const Zalo = (props) => {
270
270
  validateTags({
271
271
  content: message,
272
272
  tagsParam: tags,
273
+ injectedTagsParams: injectedTags,
273
274
  location,
274
275
  tagModule: getDefaultTags,
276
+ eventContextTags,
275
277
  isFullMode,
276
278
  }) || {};
277
- const { isBraceError } = tagValidationResponse;
279
+ const { unsupportedTags = [], isBraceError } = tagValidationResponse;
280
+ let tagError = '';
281
+ if (unsupportedTags.length > 0) {
282
+ tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
283
+ unsupportedTags,
284
+ });
285
+ }
278
286
  if (isBraceError) {
279
- return formatMessage(globalMessages.unbalanacedCurlyBraces);
287
+ tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
280
288
  }
281
- return '';
289
+ return tagError;
282
290
  };
283
291
 
284
292
  //this function is used for checking errror validation in this it validate tags error and length error
@@ -1,42 +0,0 @@
1
- import PropTypes from "prop-types";
2
- import { FormattedMessage } from "react-intl";
3
- import CapButton from "@capillarytech/cap-ui-library/CapButton";
4
- import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
5
- import messages from "./messages";
6
- import React from "react";
7
-
8
- const AddTestCustomerButton = ({
9
- searchValue,
10
- handleAddTestCustomer
11
- }) => (
12
- <CapButton
13
- onClick={handleAddTestCustomer}
14
- type="flat"
15
- size="small"
16
- className="test-customer-add-btn"
17
- prefix={
18
- <CapIcon
19
- type="add-profile"
20
- className="add-test-customer-icon"
21
- />
22
- }
23
- >
24
- <FormattedMessage
25
- {...messages.addTestCustomerWithValue}
26
- values={{
27
- searchValue: (
28
- <span className="test-customer-add-btn-value" title={searchValue || ""}>
29
- "{searchValue}"
30
- </span>
31
- ),
32
- }}
33
- />
34
- </CapButton>
35
- );
36
-
37
- AddTestCustomerButton.propTypes = {
38
- searchValue: PropTypes.string.isRequired,
39
- handleAddTestCustomer: PropTypes.func.isRequired
40
- };
41
-
42
- export default AddTestCustomerButton;
@@ -1,284 +0,0 @@
1
- import CapModal from "@capillarytech/cap-ui-library/CapModal";
2
- import CapButton from "@capillarytech/cap-ui-library/CapButton";
3
- import CapInput from "@capillarytech/cap-ui-library/CapInput";
4
- import CapLabel from "@capillarytech/cap-ui-library/CapLabel";
5
- import CapRow from "@capillarytech/cap-ui-library/CapRow";
6
- import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
7
- import CapSpin from "@capillarytech/cap-ui-library/CapSpin";
8
- import { FormattedMessage, injectIntl } from "react-intl";
9
- import messages from "./messages";
10
- import React, { useState, useCallback, useEffect, useRef } from "react";
11
- import { CHANNELS, IDENTIFIER_TYPE_EMAIL, IDENTIFIER_TYPE_MOBILE, INPUT_HAS_ERROR_CLASS } from "./constants";
12
- import { getMembersLookup } from '../../services/api';
13
- import { isValidEmail, isValidMobile, formatPhoneNumber } from "../../utils/commonUtils";
14
-
15
- const CustomerCreationModal = ({
16
- customerModal,
17
- setCustomerModal,
18
- channel,
19
- customerData,
20
- setCustomerData,
21
- onSave,
22
- intl,
23
- }) => {
24
- const [validationErrors, setValidationErrors] = useState({
25
- email: "",
26
- mobile: ""
27
- });
28
- const [isLoading, setIsLoading] = useState(false);
29
- const [lookupLoading, setLookupLoading] = useState(null); // null | IDENTIFIER_TYPE_EMAIL | IDENTIFIER_TYPE_MOBILE
30
-
31
- // Refs to track the latest values for async validation
32
- const latestEmailRef = useRef(customerData.email || "");
33
- const latestMobileRef = useRef(customerData.mobile || "");
34
-
35
- // Helper function to render validation errors
36
- const renderValidationError = (error) => {
37
- if (!error) return null;
38
-
39
- return (
40
- <div className="customer-creation-modal-validation-error">
41
- {typeof error === 'string' ? error : <FormattedMessage {...error} />}
42
- </div>
43
- );
44
- };
45
-
46
- // Check if required fields are filled based on channel
47
- const isRequiredFieldMissing = () => {
48
- if (channel === CHANNELS.EMAIL && !customerData.email) {
49
- return true;
50
- }
51
- if (channel === CHANNELS.SMS && !customerData.mobile) {
52
- return true;
53
- }
54
- return false;
55
- };
56
-
57
- // Check if save button should be disabled
58
- const isSaveDisabled = () => {
59
- return (
60
- validationErrors.email ||
61
- validationErrors.mobile ||
62
- isRequiredFieldMissing() ||
63
- !!lookupLoading
64
- );
65
- };
66
-
67
- // Perform lookup (same logic as in index.js)
68
- const performLookup = useCallback(async (identifierType, value) => {
69
- try {
70
- const response = await getMembersLookup(identifierType, value);
71
- const success = response?.success && !response?.status?.isError;
72
- const res = response?.response || {};
73
- const exists = res.exists || false;
74
- const details = res.customerDetails || [];
75
- if (!success) {
76
- const errorMessage = response?.message || response?.status?.message
77
- if (errorMessage?.toLowerCase().includes("merged customer found")) {
78
- return { success: true, exists: true, details: [] };
79
- }
80
- }
81
-
82
- return { success, exists, details };
83
- } catch (error) {
84
- return { success: false, exists: false, details: [] };
85
- }
86
- }, []);
87
-
88
- // Handle validation and lookup for email or mobile
89
- const handleLookupValidation = useCallback(async (type, value) => {
90
- const isEmail = type === IDENTIFIER_TYPE_EMAIL;
91
- const ref = isEmail ? latestEmailRef : latestMobileRef;
92
- const field = isEmail ? IDENTIFIER_TYPE_EMAIL : IDENTIFIER_TYPE_MOBILE;
93
-
94
- if (!value) {
95
- if (ref.current === value) {
96
- setValidationErrors(prev => ({ ...prev, [field]: "" }));
97
- }
98
- return;
99
- }
100
-
101
- if (isEmail && !isValidEmail(value)) {
102
- if (ref.current === value) {
103
- setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_EMAIL]: "Please enter a valid email address" }));
104
- }
105
- return;
106
- }
107
- if (!isEmail && !isValidMobile(value)) {
108
- if (ref.current === value) {
109
- setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_MOBILE]: "Please enter a valid mobile number" }));
110
- }
111
- return;
112
- }
113
-
114
- setLookupLoading(field);
115
- try {
116
- const { success, exists } = await performLookup(type, value);
117
-
118
- if (ref.current === value) {
119
- if (success && exists) {
120
- setValidationErrors(prev => ({
121
- ...prev,
122
- [field]: isEmail ? messages.emailAlreadyExists : messages.mobileAlreadyExists
123
- }));
124
- } else {
125
- setValidationErrors(prev => ({ ...prev, [field]: "" }));
126
- }
127
- }
128
- } finally {
129
- setLookupLoading(null);
130
- }
131
- }, [performLookup]);
132
-
133
- // Debounce timer refs
134
- const emailTimeoutRef = React.useRef(null);
135
- const mobileTimeoutRef = React.useRef(null);
136
-
137
- // Handle email change with debounced validation
138
- const handleEmailChange = (e) => {
139
- const email = e.target.value;
140
- latestEmailRef.current = email; // Update the latest email ref
141
- setCustomerData({ ...customerData, email });
142
-
143
- // Clear previous timeout
144
- if (emailTimeoutRef.current) {
145
- clearTimeout(emailTimeoutRef.current);
146
- }
147
-
148
- // Set new timeout for validation
149
- emailTimeoutRef.current = setTimeout(() => {
150
- handleLookupValidation(IDENTIFIER_TYPE_EMAIL, email);
151
- }, 500);
152
- };
153
-
154
- // Handle mobile change with debounced validation
155
- const handleMobileChange = (e) => {
156
- const rawValue = e.target.value;
157
- const formattedMobile = formatPhoneNumber(rawValue);
158
- latestMobileRef.current = formattedMobile; // Update the latest mobile ref
159
- setCustomerData({ ...customerData, mobile: formattedMobile });
160
-
161
- // Clear previous timeout
162
- if (mobileTimeoutRef.current) {
163
- clearTimeout(mobileTimeoutRef.current);
164
- }
165
-
166
- // Set new timeout for validation
167
- mobileTimeoutRef.current = setTimeout(() => {
168
- handleLookupValidation(IDENTIFIER_TYPE_MOBILE, formattedMobile);
169
- }, 500);
170
- };
171
-
172
- // Update refs when customerData changes externally
173
- useEffect(() => {
174
- latestEmailRef.current = customerData.email || "";
175
- latestMobileRef.current = customerData.mobile || "";
176
- }, [customerData.email, customerData.mobile]);
177
-
178
- // Cleanup timeouts on unmount
179
- useEffect(() => {
180
- return () => {
181
- if (emailTimeoutRef.current) {
182
- clearTimeout(emailTimeoutRef.current);
183
- }
184
- if (mobileTimeoutRef.current) {
185
- clearTimeout(mobileTimeoutRef.current);
186
- }
187
- };
188
- }, []);
189
-
190
- return (
191
- <CapModal
192
- visible={customerModal[0]}
193
- onCancel={() => setCustomerModal([false, ""])}
194
- centered={true}
195
- width={500}
196
- maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
197
- footer={
198
- <CapRow justify="start" gutter={8}>
199
- <CapButton
200
- type="primary"
201
- onClick={() => onSave(validationErrors, setIsLoading)}
202
- disabled={isSaveDisabled() || lookupLoading}
203
- loading={isLoading}
204
- >
205
- <FormattedMessage {...messages.saveButton} />
206
- </CapButton>
207
- <CapButton
208
- type="secondary"
209
- onClick={() => setCustomerModal([false, ""])}
210
- disabled={isLoading || lookupLoading}
211
- >
212
- <FormattedMessage {...messages.cancelButton} />
213
- </CapButton>
214
- </CapRow>
215
- }
216
- title={<FormattedMessage {...messages.customerCreationModalTitle} />}
217
- wrapClassName="common-test-preview-modal-wrap"
218
- className={`common-test-preview-modal${lookupLoading ? ' customer-creation-modal--lookup-loading' : ''}`}
219
- >
220
- <CapRow className="customer-creation-modal-row">
221
- <CapColumn span={24}>
222
- <span className="customer-creation-modal-description">
223
- <FormattedMessage {...messages.customerCreationModalDescription} />
224
- </span>
225
- </CapColumn>
226
- </CapRow>
227
-
228
- <CapRow className="customer-creation-modal-row">
229
- <CapColumn span={24}>
230
- <CapLabel type="label1" className="customer-creation-modal-label">
231
- <FormattedMessage {...messages.customerName} /> <span className="customer-creation-modal-optional">(Optional)</span>
232
- </CapLabel>
233
- <CapInput
234
- value={customerData.name || ""}
235
- onChange={e =>
236
- setCustomerData({ ...customerData, name: e.target.value })
237
- }
238
- placeholder={intl.formatMessage(messages.customerNamePlaceholder)}
239
- size="default"
240
- className="customer-creation-modal-input"
241
- />
242
- </CapColumn>
243
- </CapRow>
244
-
245
- <CapRow className="customer-creation-modal-row customer-creation-modal-row--email">
246
- <CapColumn span={24}>
247
- <CapLabel type="label1" className="customer-creation-modal-label">
248
- <FormattedMessage {...messages.customerEmail} /> {channel !== CHANNELS.EMAIL && <span className="customer-creation-modal-optional">(Optional)</span>}
249
- </CapLabel>
250
- <CapInput
251
- value={customerData.email || ""}
252
- onChange={handleEmailChange}
253
- placeholder={intl.formatMessage(messages.customerEmailPlaceholder)}
254
- size="default"
255
- className={`customer-creation-modal-input${validationErrors.email ? INPUT_HAS_ERROR_CLASS : ''}`}
256
- disabled={!!lookupLoading}
257
- suffix={lookupLoading === IDENTIFIER_TYPE_EMAIL ? <CapSpin size="small" /> : null}
258
- />
259
- {renderValidationError(validationErrors.email)}
260
- </CapColumn>
261
- </CapRow>
262
-
263
- <CapRow className="customer-creation-modal-row customer-creation-modal-row--last">
264
- <CapColumn span={24}>
265
- <CapLabel type="label1" className="customer-creation-modal-label">
266
- <FormattedMessage {...messages.customerMobile} /> {channel !== CHANNELS.SMS && <span className="customer-creation-modal-optional">(Optional)</span>}
267
- </CapLabel>
268
- <CapInput
269
- value={customerData.mobile || ""}
270
- onChange={handleMobileChange}
271
- placeholder={intl.formatMessage(messages.customerMobilePlaceholder)}
272
- size="default"
273
- className={`customer-creation-modal-input${validationErrors.mobile ? INPUT_HAS_ERROR_CLASS : ''}`}
274
- disabled={!!lookupLoading}
275
- suffix={lookupLoading === IDENTIFIER_TYPE_MOBILE ? <CapSpin size="small" /> : null}
276
- />
277
- {renderValidationError(validationErrors.mobile)}
278
- </CapColumn>
279
- </CapRow>
280
- </CapModal>
281
- );
282
- };
283
-
284
- export default injectIntl(CustomerCreationModal);
@@ -1,72 +0,0 @@
1
- import CapModal from "@capillarytech/cap-ui-library/CapModal";
2
- import { FormattedMessage, injectIntl } from "react-intl";
3
- import messages from "./messages";
4
- import React, { useState } from "react";
5
- import { CapCard, CapRow, CapColumn } from "@capillarytech/cap-ui-library";
6
- import { CHANNELS } from "./constants";
7
- import CapButton from "@capillarytech/cap-ui-library/CapButton";
8
- import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
9
-
10
-
11
- const ExistingCustomerModal = ({ customerModal, setCustomerModal, customerData, channel, onSave, intl }) => {
12
- const [isLoading, setIsLoading] = useState(false);
13
- return (
14
- <CapModal
15
- visible={customerModal[0]}
16
- onCancel={() => setCustomerModal([false, ""])}
17
- centered={true}
18
- width={500}
19
- maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
20
- footer={
21
- <CapRow justify="start">
22
- <CapButton
23
- type="primary"
24
- onClick={() => onSave({},setIsLoading)}
25
- loading={isLoading}
26
- >
27
- <FormattedMessage {...messages.saveButton} />
28
- </CapButton>
29
- <CapButton
30
- type="secondary"
31
- onClick={() => setCustomerModal([false, ""])}
32
- disabled={isLoading}
33
- >
34
- <FormattedMessage {...messages.cancelButton} />
35
- </CapButton>
36
- </CapRow>
37
- }
38
- title={intl.formatMessage(messages.customerCreationModalTitle)}
39
- wrapClassName="common-test-preview-modal-wrap existing-customer-modal-wrap"
40
- className="common-test-preview-modal"
41
- >
42
- <div className="existing-customer-modal">
43
- <CapRow className="existing-customer-modal-intro-row">
44
- <FormattedMessage {...messages.existingCustomerModalDescription} />
45
- </CapRow>
46
- <CapCard className="existing-customer-modal-card">
47
- <CapRow className="existing-customer-modal-card-row">
48
- <CapColumn className="existing-customer-modal-avatar">
49
- <CapIcon type="user-profile" className="existing-customer-modal-avatar-icon" />
50
- </CapColumn>
51
- <CapColumn className="existing-customer-modal-details">
52
- <CapRow className="existing-customer-modal-name">
53
- {customerData.name || "-"}
54
- </CapRow>
55
- <CapColumn className="existing-customer-modal-meta">
56
- {channel === CHANNELS.EMAIL && customerData.email && (
57
- <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerEmail} />: </span> {customerData.email}</CapRow>
58
- )}
59
- {channel === CHANNELS.SMS && customerData.mobile && (
60
- <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerMobile} />: </span>{customerData.mobile}</CapRow>
61
- )}
62
- <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerID} />: </span>{customerData.customerId}</CapRow>
63
- </CapColumn>
64
- </CapColumn>
65
- </CapRow>
66
- </CapCard>
67
- </div>
68
- </CapModal>
69
- );
70
- };
71
-
72
- export default injectIntl(ExistingCustomerModal);
@@ -1,66 +0,0 @@
1
- /**
2
- * Tests for AddTestCustomerButton Component
3
- *
4
- * The parent (index.js) only renders this button when channel is EMAIL/SMS and value is valid.
5
- * This component always renders the button when mounted; visibility is the parent's responsibility.
6
- */
7
-
8
- import React from 'react';
9
- import { render, screen, fireEvent } from '@testing-library/react';
10
- import { IntlProvider } from 'react-intl';
11
- import AddTestCustomerButton from '../AddTestCustomer';
12
-
13
- const mockMessages = {
14
- 'app.v2Components.TestAndPreviewSlidebox.addTestCustomerWithValue': 'Add {searchValue} as Test Customer',
15
- };
16
-
17
- const TestWrapper = ({ children }) => (
18
- <IntlProvider locale="en" messages={mockMessages}>
19
- {children}
20
- </IntlProvider>
21
- );
22
-
23
- describe('AddTestCustomerButton', () => {
24
- const defaultProps = {
25
- searchValue: 'user@example.com',
26
- handleAddTestCustomer: jest.fn(),
27
- };
28
-
29
- beforeEach(() => {
30
- jest.clearAllMocks();
31
- });
32
-
33
- it('should render button with searchValue in message', () => {
34
- render(
35
- <TestWrapper>
36
- <AddTestCustomerButton {...defaultProps} />
37
- </TestWrapper>
38
- );
39
- const button = screen.getByRole('button', { name: /add.*test customer/i });
40
- expect(button).toBeTruthy();
41
- });
42
-
43
- it('should show searchValue in button text', () => {
44
- render(
45
- <TestWrapper>
46
- <AddTestCustomerButton {...defaultProps} searchValue="user@example.com" />
47
- </TestWrapper>
48
- );
49
- expect(screen.getByRole('button', { name: /user@example.com/i })).toBeTruthy();
50
- });
51
-
52
- it('should call handleAddTestCustomer when button is clicked', () => {
53
- const handleAddTestCustomer = jest.fn();
54
- render(
55
- <TestWrapper>
56
- <AddTestCustomerButton
57
- searchValue="user@example.com"
58
- handleAddTestCustomer={handleAddTestCustomer}
59
- />
60
- </TestWrapper>
61
- );
62
- const button = screen.getByRole('button', { name: /add.*test customer/i });
63
- fireEvent.click(button);
64
- expect(handleAddTestCustomer).toHaveBeenCalledTimes(1);
65
- });
66
- });