@hubspot/ui-extensions 0.11.5 → 0.12.0
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.
- package/dist/__tests__/crm/hooks/useAssociations.spec.js +96 -0
- package/dist/__tests__/crm/hooks/useCrmProperties.spec.js +170 -1
- package/dist/crm/hooks/useAssociations.d.ts +2 -0
- package/dist/crm/hooks/useAssociations.js +87 -0
- package/dist/crm/hooks/useCrmProperties.d.ts +5 -1
- package/dist/crm/hooks/useCrmProperties.js +81 -2
- package/dist/hs-internal/__tests__/createRemoteComponentInternal.spec.d.ts +1 -0
- package/dist/hs-internal/__tests__/createRemoteComponentInternal.spec.js +139 -0
- package/dist/hs-internal/index.d.ts +35 -0
- package/dist/hs-internal/index.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/shared/remoteComponents.d.ts +9 -0
- package/dist/shared/remoteComponents.js +9 -0
- package/dist/shared/types/components/accordion.d.ts +5 -5
- package/dist/shared/types/components/alert.d.ts +2 -2
- package/dist/shared/types/components/button-row.d.ts +5 -2
- package/dist/shared/types/components/button.d.ts +16 -10
- package/dist/shared/types/components/chart.d.ts +3 -3
- package/dist/shared/types/components/description-list.d.ts +2 -2
- package/dist/shared/types/components/dropdown.d.ts +8 -8
- package/dist/shared/types/components/empty-state.d.ts +5 -7
- package/dist/shared/types/components/error-state.d.ts +2 -2
- package/dist/shared/types/components/form.d.ts +2 -2
- package/dist/shared/types/components/heading.d.ts +1 -1
- package/dist/shared/types/components/icon.d.ts +4 -5
- package/dist/shared/types/components/illustration.d.ts +12 -0
- package/dist/shared/types/components/image.d.ts +9 -4
- package/dist/shared/types/components/index.d.ts +1 -0
- package/dist/shared/types/components/inputs.d.ts +61 -63
- package/dist/shared/types/components/layouts.d.ts +17 -24
- package/dist/shared/types/components/link.d.ts +8 -5
- package/dist/shared/types/components/loading-spinner.d.ts +3 -3
- package/dist/shared/types/components/modal.d.ts +5 -5
- package/dist/shared/types/components/panel.d.ts +7 -7
- package/dist/shared/types/components/progress-bar.d.ts +4 -4
- package/dist/shared/types/components/score.d.ts +13 -0
- package/dist/shared/types/components/score.js +1 -0
- package/dist/shared/types/components/selects.d.ts +11 -20
- package/dist/shared/types/components/statistics.d.ts +2 -2
- package/dist/shared/types/components/status-tag.d.ts +5 -5
- package/dist/shared/types/components/step-indicator.d.ts +5 -7
- package/dist/shared/types/components/table.d.ts +22 -12
- package/dist/shared/types/components/tabs.d.ts +10 -10
- package/dist/shared/types/components/tag.d.ts +2 -2
- package/dist/shared/types/components/text.d.ts +15 -21
- package/dist/shared/types/components/tile.d.ts +2 -2
- package/dist/shared/types/components/toggle.d.ts +12 -14
- package/dist/shared/types/components/toggleInputs.d.ts +26 -19
- package/dist/shared/types/components/tooltip.d.ts +1 -1
- package/dist/shared/types/crm.d.ts +52 -0
- package/dist/shared/types/http-requests.d.ts +2 -2
- package/dist/shared/types/index.d.ts +1 -1
- package/dist/shared/types/index.js +1 -0
- package/dist/shared/types/shared.d.ts +128 -78
- package/dist/shared/types/shared.js +123 -78
- package/dist/shared/types/worker-globals.d.ts +11 -10
- package/dist/testing/__tests__/mocks.useAssociations.spec.js +92 -4
- package/dist/testing/__tests__/mocks.useCrmProperties.spec.js +55 -7
- package/dist/testing/internal/mocks/mock-hooks.js +4 -0
- package/package.json +4 -3
|
@@ -18,151 +18,196 @@ export class FormSubmitExtensionEvent extends ExtensionEvent {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
export const iconNames = {
|
|
21
|
-
success: 'success',
|
|
22
|
-
remove: 'remove',
|
|
23
21
|
add: 'add',
|
|
22
|
+
appointment: 'appointment',
|
|
23
|
+
approvals: 'approvals',
|
|
24
|
+
artificialIntelligence: 'artificialIntelligence',
|
|
25
|
+
artificialIntelligenceEnhanced: 'artificialIntelligenceEnhanced',
|
|
24
26
|
attach: 'attach',
|
|
25
|
-
|
|
27
|
+
bank: 'bank',
|
|
28
|
+
block: 'block',
|
|
29
|
+
book: 'knowledgeBase',
|
|
30
|
+
bulb: 'bulb',
|
|
31
|
+
callTranscript: 'callTranscript',
|
|
32
|
+
calling: 'calling',
|
|
33
|
+
callingHangup: 'callingHangup',
|
|
34
|
+
callingMade: 'callingMade',
|
|
35
|
+
callingMissed: 'callingMissed',
|
|
36
|
+
callingVoicemail: 'callingVoicemail',
|
|
37
|
+
campaigns: 'campaigns',
|
|
38
|
+
cap: 'cap',
|
|
39
|
+
checkCircle: 'checkCircle',
|
|
40
|
+
circleFilled: 'circleFilled',
|
|
41
|
+
circleHollow: 'circleHollow',
|
|
42
|
+
clock: 'time',
|
|
43
|
+
comment: 'comments',
|
|
44
|
+
contact: 'contacts',
|
|
26
45
|
copy: 'duplicate',
|
|
46
|
+
crm: 'crm',
|
|
47
|
+
dataSync: 'dataSync',
|
|
48
|
+
date: 'date',
|
|
49
|
+
delay: 'delay',
|
|
27
50
|
delete: 'delete',
|
|
51
|
+
description: 'description',
|
|
52
|
+
developerProjects: 'developerProjects',
|
|
53
|
+
documents: 'documents',
|
|
54
|
+
downCarat: 'downCarat',
|
|
55
|
+
download: 'download',
|
|
28
56
|
edit: 'edit',
|
|
57
|
+
ellipses: 'ellipses',
|
|
29
58
|
email: 'email',
|
|
59
|
+
emailOpen: 'emailOpen',
|
|
60
|
+
emailThreadedReplies: 'emailThreadedReplies',
|
|
61
|
+
enrichment: 'enrichment',
|
|
62
|
+
enroll: 'enroll',
|
|
30
63
|
exclamation: 'exclamation',
|
|
31
|
-
|
|
32
|
-
home: 'home',
|
|
33
|
-
location: 'location',
|
|
34
|
-
upCarat: 'upCarat',
|
|
35
|
-
downCarat: 'downCarat',
|
|
36
|
-
warning: 'warning',
|
|
37
|
-
shoppingCart: 'cart',
|
|
38
|
-
clock: 'time',
|
|
39
|
-
comment: 'comments',
|
|
40
|
-
contact: 'contacts',
|
|
41
|
-
star: 'favorite',
|
|
42
|
-
file: 'file',
|
|
43
|
-
reports: 'reports',
|
|
44
|
-
video: 'video',
|
|
45
|
-
robot: 'simpleBot',
|
|
46
|
-
refresh: 'refresh',
|
|
64
|
+
exclamationCircle: 'exclamationCircle',
|
|
47
65
|
faceHappy: 'emoji',
|
|
66
|
+
faceHappyFilled: 'emojiFillHappy',
|
|
48
67
|
faceNeutral: 'emojiLineNeutral',
|
|
68
|
+
faceNeutralFilled: 'emojiFillNeutral',
|
|
49
69
|
faceSad: 'emojiLineSad',
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
imageGallery: 'imageGallery',
|
|
56
|
-
search: 'search',
|
|
57
|
-
save: 'saveEditableView',
|
|
58
|
-
notification: 'notification',
|
|
59
|
-
bulb: 'bulb',
|
|
60
|
-
settings: 'settings',
|
|
70
|
+
faceSadFilled: 'emojiFillSad',
|
|
71
|
+
facebook: 'socialBlockFacebook',
|
|
72
|
+
favoriteHollow: 'favoriteHollow',
|
|
73
|
+
file: 'file',
|
|
74
|
+
filledXCircleIcon: 'filledXCircleIcon',
|
|
61
75
|
filter: 'filter',
|
|
76
|
+
flame: 'highlyEngagedLead',
|
|
77
|
+
folder: 'folder',
|
|
78
|
+
folderOpen: 'folderOpen',
|
|
79
|
+
forward: 'forward',
|
|
62
80
|
gauge: 'gauge',
|
|
63
|
-
enroll: 'enroll',
|
|
64
81
|
generateChart: 'generateChart',
|
|
65
82
|
gift: 'gift',
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
globe: 'language',
|
|
84
|
+
globeLine: 'globe',
|
|
85
|
+
goal: 'goal',
|
|
86
|
+
googlePlus: 'socialBlockGoogleplus',
|
|
87
|
+
guidedActions: 'guidedActions',
|
|
88
|
+
hash: 'numericDataType',
|
|
89
|
+
hide: 'hide',
|
|
90
|
+
home: 'home',
|
|
91
|
+
hubDB: 'hubDB',
|
|
68
92
|
image: 'insertImage',
|
|
69
|
-
|
|
93
|
+
imageGallery: 'imageGallery',
|
|
94
|
+
inbox: 'inbox',
|
|
95
|
+
info: 'info',
|
|
96
|
+
infoNoCircle: 'infoNoCircle',
|
|
70
97
|
insertVideo: 'insertVideo',
|
|
98
|
+
instagram: 'socialBlockInstagram',
|
|
99
|
+
integrations: 'integrations',
|
|
71
100
|
invoice: 'invoice',
|
|
72
101
|
key: 'key',
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
language: 'language',
|
|
103
|
+
left: 'left',
|
|
104
|
+
lessCircle: 'lessCircle',
|
|
75
105
|
lesson: 'lesson',
|
|
106
|
+
light: 'light',
|
|
76
107
|
link: 'link',
|
|
108
|
+
linkedin: 'socialBlockLinkedin',
|
|
77
109
|
listView: 'listView',
|
|
110
|
+
location: 'location',
|
|
78
111
|
locked: 'locked',
|
|
79
112
|
mention: 'mention',
|
|
80
113
|
messages: 'messages',
|
|
81
114
|
mobile: 'mobile',
|
|
115
|
+
moreCircle: 'moreCircle',
|
|
116
|
+
notEditable: 'notEditable',
|
|
117
|
+
notification: 'notification',
|
|
82
118
|
notificationOff: 'notificationOff',
|
|
83
|
-
hash: 'numericDataType',
|
|
84
119
|
objectAssociations: 'objectAssociations',
|
|
85
120
|
objectAssociationsManyToMany: 'objectAssociationsManyToMany',
|
|
86
121
|
objectAssociationsManyToOne: 'objectAssociationsManyToOne',
|
|
87
122
|
office365: 'office365',
|
|
88
123
|
order: 'order',
|
|
89
124
|
paymentSubscriptions: 'paymentSubscriptions',
|
|
90
|
-
|
|
125
|
+
pin: 'pin',
|
|
126
|
+
pinterest: 'socialBlockPinterest',
|
|
91
127
|
powerPointFile: 'powerPointFile',
|
|
92
128
|
presentation: 'presentation',
|
|
129
|
+
product: 'product',
|
|
93
130
|
publish: 'publish',
|
|
131
|
+
question: 'question',
|
|
94
132
|
questionAnswer: 'questionAnswer',
|
|
133
|
+
questionCircle: 'questionCircle',
|
|
95
134
|
quickbooks: 'quickbooks',
|
|
135
|
+
quote: 'insertQuote',
|
|
96
136
|
readMore: 'readMore',
|
|
97
|
-
realEstateListing: 'realEstateListing',
|
|
98
137
|
readOnlyView: 'readOnlyView',
|
|
138
|
+
realEstateListing: 'realEstateListing',
|
|
99
139
|
recentlySelected: 'recentlySelected',
|
|
100
140
|
record: 'record',
|
|
101
141
|
redo: 'redo',
|
|
102
|
-
|
|
142
|
+
refresh: 'refresh',
|
|
103
143
|
registration: 'registration',
|
|
144
|
+
remove: 'remove',
|
|
104
145
|
replace: 'replace',
|
|
146
|
+
reports: 'reports',
|
|
147
|
+
right: 'right',
|
|
148
|
+
robot: 'simpleBot',
|
|
105
149
|
rotate: 'rotate',
|
|
150
|
+
rss: 'socialBlockRss',
|
|
106
151
|
salesQuote: 'salesQuote',
|
|
107
152
|
salesTemplates: 'salesTemplates',
|
|
153
|
+
save: 'saveEditableView',
|
|
154
|
+
search: 'search',
|
|
155
|
+
send: 'send',
|
|
108
156
|
sequences: 'sequences',
|
|
157
|
+
settings: 'settings',
|
|
158
|
+
shoppingCart: 'cart',
|
|
159
|
+
signal: 'signal',
|
|
160
|
+
signalPoor: 'signalPoor',
|
|
161
|
+
signature: 'signature',
|
|
162
|
+
snooze: 'snooze',
|
|
163
|
+
sortAlpAsc: 'sortAlpAsc',
|
|
164
|
+
sortAlpDesc: 'sortAlpDesc',
|
|
165
|
+
sortAmtAsc: 'sortAmtAsc',
|
|
166
|
+
sortAmtDesc: 'sortAmtDesc',
|
|
167
|
+
sortNumAsc: 'sortNumAsc',
|
|
168
|
+
sortNumDesc: 'sortNumDesc',
|
|
169
|
+
sortTableAsc: 'sortTableAsc',
|
|
170
|
+
sortTableDesc: 'sortTableDesc',
|
|
109
171
|
spellCheck: 'spellCheck',
|
|
172
|
+
sprocket: 'sprocket',
|
|
173
|
+
star: 'favorite',
|
|
174
|
+
stopRecord: 'stopRecord',
|
|
110
175
|
strike: 'strike',
|
|
176
|
+
styles: 'styles',
|
|
177
|
+
success: 'success',
|
|
111
178
|
tablet: 'tablet',
|
|
112
179
|
tag: 'tag',
|
|
113
180
|
tasks: 'tasks',
|
|
114
181
|
test: 'test',
|
|
115
|
-
|
|
116
|
-
|
|
182
|
+
text: 'text',
|
|
183
|
+
textBodyExpanded: 'textBodyExpanded',
|
|
184
|
+
textColor: 'textColor',
|
|
185
|
+
textDataType: 'textDataType',
|
|
186
|
+
textSnippet: 'textSnippet',
|
|
117
187
|
thumbsDown: 'thumbsDown',
|
|
188
|
+
thumbsUp: 'thumbsUp',
|
|
189
|
+
ticket: 'ticket',
|
|
118
190
|
translate: 'translate',
|
|
119
191
|
trophy: 'trophy',
|
|
192
|
+
twitter: 'socialBlockTwitter',
|
|
193
|
+
undo: 'undo',
|
|
194
|
+
upCarat: 'upCarat',
|
|
195
|
+
upload: 'upload',
|
|
196
|
+
video: 'video',
|
|
120
197
|
videoFile: 'videoFile',
|
|
121
198
|
videoPlayerSubtitles: 'videoPlayerSubtitles',
|
|
122
199
|
view: 'view',
|
|
123
200
|
viewDetails: 'viewDetails',
|
|
201
|
+
warning: 'warning',
|
|
124
202
|
website: 'website',
|
|
125
203
|
workflows: 'workflows',
|
|
126
|
-
zoomIn: 'zoomIn',
|
|
127
|
-
zoomOut: 'zoomOut',
|
|
128
|
-
goal: 'goal',
|
|
129
|
-
campaigns: 'campaigns',
|
|
130
|
-
cap: 'cap',
|
|
131
|
-
block: 'block',
|
|
132
|
-
bank: 'bank',
|
|
133
|
-
approvals: 'approvals',
|
|
134
|
-
appointment: 'appointment',
|
|
135
|
-
facebook: 'socialBlockFacebook',
|
|
136
|
-
googlePlus: 'socialBlockGoogleplus',
|
|
137
|
-
instagram: 'socialBlockInstagram',
|
|
138
|
-
linkedin: 'socialBlockLinkedin',
|
|
139
|
-
pinterest: 'socialBlockPinterest',
|
|
140
|
-
rss: 'socialBlockRss',
|
|
141
|
-
twitter: 'socialBlockTwitter',
|
|
142
204
|
x: 'socialBlockX',
|
|
205
|
+
xCircle: 'xCircle',
|
|
143
206
|
xing: 'socialBlockXing',
|
|
144
207
|
youtube: 'socialBlockYoutube',
|
|
145
208
|
youtubePlay: 'socialBlockYoutubeplay',
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
sortAmtAsc: 'sortAmtAsc',
|
|
149
|
-
sortAmtDesc: 'sortAmtDesc',
|
|
150
|
-
sortNumAsc: 'sortNumAsc',
|
|
151
|
-
sortNumDesc: 'sortNumDesc',
|
|
152
|
-
sortTableAsc: 'sortTableAsc',
|
|
153
|
-
sortTableDesc: 'sortTableDesc',
|
|
154
|
-
text: 'text',
|
|
155
|
-
textColor: 'textColor',
|
|
156
|
-
textDataType: 'textDataType',
|
|
157
|
-
textSnippet: 'textSnippet',
|
|
158
|
-
calling: 'calling',
|
|
159
|
-
callingHangup: 'callingHangup',
|
|
160
|
-
callingMade: 'callingMade',
|
|
161
|
-
callingMissed: 'callingMissed',
|
|
162
|
-
callingVoicemail: 'callingVoicemail',
|
|
163
|
-
faceHappyFilled: 'emojiFillHappy',
|
|
164
|
-
faceNeutralFilled: 'emojiFillNeutral',
|
|
165
|
-
faceSadFilled: 'emojiFillSad',
|
|
209
|
+
zoomIn: 'zoomIn',
|
|
210
|
+
zoomOut: 'zoomOut',
|
|
166
211
|
};
|
|
167
212
|
/** @deprecated use ExtensionEvent/FormSubmitExtensionEvent instead */
|
|
168
213
|
export class RemoteEvent {
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { Logger } from './logger.ts';
|
|
2
2
|
import { HubspotExtendFunction } from './extend.ts';
|
|
3
3
|
import type { ExtensionPoints, ExtensionPointApiContext, ExtensionPointApiActions } from './extension-points.ts';
|
|
4
|
+
export interface WorkersApi {
|
|
5
|
+
/**
|
|
6
|
+
* Hook added to worker globals so customer code can access extension context at runtime.
|
|
7
|
+
*/
|
|
8
|
+
useExtensionContext: <ExtensionPoint extends keyof ExtensionPoints>() => ExtensionPointApiContext<ExtensionPoint>;
|
|
9
|
+
/**
|
|
10
|
+
* Hook added to worker globals so customer code can access extension actions at runtime.
|
|
11
|
+
*/
|
|
12
|
+
useExtensionActions: <ExtensionPoint extends keyof ExtensionPoints>() => ExtensionPointApiActions<ExtensionPoint>;
|
|
13
|
+
}
|
|
4
14
|
export interface WorkerGlobalsInternal {
|
|
5
15
|
/**
|
|
6
16
|
* A marker that the current global is a HubSpot extension worker.
|
|
@@ -19,14 +29,5 @@ export interface WorkerGlobalsInternal {
|
|
|
19
29
|
* Namespace where all HubSpot APIs that go on the worker should live.
|
|
20
30
|
* This avoids polluting the global and reduces the possibility of customer code having collisions with our code.
|
|
21
31
|
*/
|
|
22
|
-
hsWorkerAPI:
|
|
23
|
-
/**
|
|
24
|
-
* Hook added to worker globals so customer code can access extension context at runtime.
|
|
25
|
-
*/
|
|
26
|
-
useExtensionContext: <ExtensionPoint extends keyof ExtensionPoints>() => ExtensionPointApiContext<ExtensionPoint>;
|
|
27
|
-
/**
|
|
28
|
-
* Hook added to worker globals so customer code can access extension actions at runtime.
|
|
29
|
-
*/
|
|
30
|
-
useExtensionActions: <ExtensionPoint extends keyof ExtensionPoints>() => ExtensionPointApiActions<ExtensionPoint>;
|
|
31
|
-
};
|
|
32
|
+
hsWorkerAPI: WorkersApi;
|
|
32
33
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { Text } from "../../index.js";
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { Text, Button } from "../../index.js";
|
|
4
4
|
import { createRenderer } from "../index.js";
|
|
5
5
|
import { useAssociations } from "../../crm/index.js";
|
|
6
6
|
function MyComponent() {
|
|
7
|
-
const { results, isLoading, error } = useAssociations({
|
|
7
|
+
const { results, isLoading, isRefetching, error, refetch } = useAssociations({
|
|
8
8
|
toObjectType: '0-1',
|
|
9
9
|
properties: ['firstname', 'lastname'],
|
|
10
10
|
pageLength: 10,
|
|
@@ -12,10 +12,13 @@ function MyComponent() {
|
|
|
12
12
|
if (isLoading) {
|
|
13
13
|
return _jsx(Text, { children: "Loading..." });
|
|
14
14
|
}
|
|
15
|
+
if (isRefetching) {
|
|
16
|
+
return _jsx(Text, { children: "Refetching..." });
|
|
17
|
+
}
|
|
15
18
|
if (error) {
|
|
16
19
|
return _jsx(Text, { children: "Something went wrong!" });
|
|
17
20
|
}
|
|
18
|
-
return (
|
|
21
|
+
return (_jsxs(_Fragment, { children: [results.map((result) => (_jsxs(Text, { children: [result.properties.firstname, " ", result.properties.lastname] }, result.toObjectId))), _jsx(Button, { testId: "refetchButton", onClick: () => refetch(), children: "Refetch" })] }));
|
|
19
22
|
}
|
|
20
23
|
describe('mock useAssociations', () => {
|
|
21
24
|
it('should provide a default mock implementation', () => {
|
|
@@ -31,6 +34,8 @@ describe('mock useAssociations', () => {
|
|
|
31
34
|
results: [],
|
|
32
35
|
error: new Error('Something went wrong!'),
|
|
33
36
|
isLoading: false,
|
|
37
|
+
isRefetching: false,
|
|
38
|
+
refetch: async () => { },
|
|
34
39
|
pagination: {
|
|
35
40
|
hasNextPage: false,
|
|
36
41
|
hasPreviousPage: false,
|
|
@@ -44,4 +49,87 @@ describe('mock useAssociations', () => {
|
|
|
44
49
|
const { find } = render(_jsx(MyComponent, {}));
|
|
45
50
|
expect(find(Text).text).toEqual('Something went wrong!');
|
|
46
51
|
});
|
|
52
|
+
it('should allow tracking refetch calls with a custom spy', () => {
|
|
53
|
+
const { render, mocks, findByTestId } = createRenderer('crm.record.tab');
|
|
54
|
+
const refetchSpy = vi.fn().mockResolvedValue(undefined);
|
|
55
|
+
mocks.useAssociations.nextResult({
|
|
56
|
+
results: [
|
|
57
|
+
{
|
|
58
|
+
toObjectId: 1,
|
|
59
|
+
associationTypes: [],
|
|
60
|
+
properties: { firstname: 'John', lastname: 'Doe' },
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
error: null,
|
|
64
|
+
isLoading: false,
|
|
65
|
+
isRefetching: false,
|
|
66
|
+
refetch: refetchSpy,
|
|
67
|
+
pagination: {
|
|
68
|
+
hasNextPage: false,
|
|
69
|
+
hasPreviousPage: false,
|
|
70
|
+
currentPage: 1,
|
|
71
|
+
pageSize: 10,
|
|
72
|
+
nextPage: () => { },
|
|
73
|
+
previousPage: () => { },
|
|
74
|
+
reset: () => { },
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
render(_jsx(MyComponent, {}));
|
|
78
|
+
findByTestId(Button, 'refetchButton').trigger('onClick');
|
|
79
|
+
expect(refetchSpy).toHaveBeenCalledTimes(1);
|
|
80
|
+
});
|
|
81
|
+
it('should allow mocking isRefetching state during refetch', () => {
|
|
82
|
+
const { render, mocks } = createRenderer('crm.record.tab');
|
|
83
|
+
mocks.useAssociations.nextResult({
|
|
84
|
+
results: [],
|
|
85
|
+
error: null,
|
|
86
|
+
isLoading: false,
|
|
87
|
+
isRefetching: true,
|
|
88
|
+
refetch: async () => { },
|
|
89
|
+
pagination: {
|
|
90
|
+
hasNextPage: false,
|
|
91
|
+
hasPreviousPage: false,
|
|
92
|
+
currentPage: 1,
|
|
93
|
+
pageSize: 10,
|
|
94
|
+
nextPage: () => { },
|
|
95
|
+
previousPage: () => { },
|
|
96
|
+
reset: () => { },
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
const { find } = render(_jsx(MyComponent, {}));
|
|
100
|
+
expect(find(Text).text).toEqual('Refetching...');
|
|
101
|
+
});
|
|
102
|
+
it('should allow providing a custom refetch implementation', () => {
|
|
103
|
+
const { render, mocks, findByTestId } = createRenderer('crm.record.tab');
|
|
104
|
+
const refetchSpy = vi.fn().mockResolvedValue(undefined);
|
|
105
|
+
const customData = { customKey: 'customValue' };
|
|
106
|
+
mocks.useAssociations.nextResult({
|
|
107
|
+
results: [
|
|
108
|
+
{
|
|
109
|
+
toObjectId: 1,
|
|
110
|
+
associationTypes: [],
|
|
111
|
+
properties: { firstname: 'Test', lastname: 'User' },
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
error: null,
|
|
115
|
+
isLoading: false,
|
|
116
|
+
isRefetching: false,
|
|
117
|
+
refetch: async () => {
|
|
118
|
+
await refetchSpy(customData);
|
|
119
|
+
},
|
|
120
|
+
pagination: {
|
|
121
|
+
hasNextPage: false,
|
|
122
|
+
hasPreviousPage: false,
|
|
123
|
+
currentPage: 1,
|
|
124
|
+
pageSize: 10,
|
|
125
|
+
nextPage: () => { },
|
|
126
|
+
previousPage: () => { },
|
|
127
|
+
reset: () => { },
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
render(_jsx(MyComponent, {}));
|
|
131
|
+
findByTestId(Button, 'refetchButton').trigger('onClick');
|
|
132
|
+
expect(refetchSpy).toHaveBeenCalledTimes(1);
|
|
133
|
+
expect(refetchSpy).toHaveBeenCalledWith(customData);
|
|
134
|
+
});
|
|
47
135
|
});
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { Text } from "../../index.js";
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { Text, Button } from "../../index.js";
|
|
4
4
|
import { createRenderer } from "../index.js";
|
|
5
5
|
import { useCrmProperties } from "../../crm/index.js";
|
|
6
6
|
function MyComponent() {
|
|
7
|
-
const { properties, isLoading, error } = useCrmProperties([
|
|
8
|
-
'firstname',
|
|
9
|
-
'lastname',
|
|
10
|
-
]);
|
|
7
|
+
const { properties, isLoading, isRefetching, error, refetch } = useCrmProperties(['firstname', 'lastname']);
|
|
11
8
|
if (isLoading) {
|
|
12
9
|
return _jsx(Text, { children: "Loading..." });
|
|
13
10
|
}
|
|
11
|
+
if (isRefetching) {
|
|
12
|
+
return _jsx(Text, { children: "Refetching..." });
|
|
13
|
+
}
|
|
14
14
|
if (error) {
|
|
15
15
|
return _jsx(Text, { children: "Something went wrong!" });
|
|
16
16
|
}
|
|
17
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["First name: ", properties.firstname] }), _jsxs(Text, { children: ["Last name: ", properties.lastname] })] }));
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["First name: ", properties.firstname] }), _jsxs(Text, { children: ["Last name: ", properties.lastname] }), _jsx(Button, { testId: "refetchButton", onClick: () => refetch(), children: "Refetch" })] }));
|
|
18
18
|
}
|
|
19
19
|
describe('mock useCrmProperties', () => {
|
|
20
20
|
it('should provide a default mock implementation', () => {
|
|
@@ -31,6 +31,8 @@ describe('mock useCrmProperties', () => {
|
|
|
31
31
|
properties: {},
|
|
32
32
|
error: new Error('Something went wrong!'),
|
|
33
33
|
isLoading: false,
|
|
34
|
+
isRefetching: false,
|
|
35
|
+
refetch: () => Promise.resolve(),
|
|
34
36
|
});
|
|
35
37
|
const { find } = render(_jsx(MyComponent, {}));
|
|
36
38
|
expect(find(Text).text).toEqual('Something went wrong!');
|
|
@@ -46,6 +48,8 @@ describe('mock useCrmProperties', () => {
|
|
|
46
48
|
properties,
|
|
47
49
|
error: null,
|
|
48
50
|
isLoading: false,
|
|
51
|
+
isRefetching: false,
|
|
52
|
+
refetch: async () => { },
|
|
49
53
|
};
|
|
50
54
|
});
|
|
51
55
|
render(_jsx(MyComponent, {}));
|
|
@@ -55,4 +59,48 @@ describe('mock useCrmProperties', () => {
|
|
|
55
59
|
expect(firstNameText.isMatch(Text) && firstNameText.text).toEqual('First name: FIRSTNAME');
|
|
56
60
|
expect(lastNameText.isMatch(Text) && lastNameText.text).toEqual('Last name: LASTNAME');
|
|
57
61
|
});
|
|
62
|
+
it('should allow tracking refetch calls with a custom spy', () => {
|
|
63
|
+
const { render, mocks, findByTestId } = createRenderer('crm.record.tab');
|
|
64
|
+
const refetchSpy = vi.fn().mockResolvedValue(undefined);
|
|
65
|
+
mocks.useCrmProperties.nextResult({
|
|
66
|
+
properties: { firstname: 'John', lastname: 'Doe' },
|
|
67
|
+
error: null,
|
|
68
|
+
isLoading: false,
|
|
69
|
+
isRefetching: false,
|
|
70
|
+
refetch: refetchSpy,
|
|
71
|
+
});
|
|
72
|
+
render(_jsx(MyComponent, {}));
|
|
73
|
+
findByTestId(Button, 'refetchButton').trigger('onClick');
|
|
74
|
+
expect(refetchSpy).toHaveBeenCalledTimes(1);
|
|
75
|
+
});
|
|
76
|
+
it('should allow mocking isRefetching state during refetch', () => {
|
|
77
|
+
const { render, mocks } = createRenderer('crm.record.tab');
|
|
78
|
+
mocks.useCrmProperties.nextResult({
|
|
79
|
+
properties: {},
|
|
80
|
+
error: null,
|
|
81
|
+
isLoading: false,
|
|
82
|
+
isRefetching: true,
|
|
83
|
+
refetch: async () => { },
|
|
84
|
+
});
|
|
85
|
+
const { find } = render(_jsx(MyComponent, {}));
|
|
86
|
+
expect(find(Text).text).toEqual('Refetching...');
|
|
87
|
+
});
|
|
88
|
+
it('should allow providing a custom refetch implementation', () => {
|
|
89
|
+
const { render, mocks, findByTestId } = createRenderer('crm.record.tab');
|
|
90
|
+
const refetchSpy = vi.fn().mockResolvedValue(undefined);
|
|
91
|
+
const customData = { customKey: 'customValue' };
|
|
92
|
+
mocks.useCrmProperties.nextResult({
|
|
93
|
+
properties: { firstname: 'Test Value', lastname: 'Test' },
|
|
94
|
+
error: null,
|
|
95
|
+
isLoading: false,
|
|
96
|
+
isRefetching: false,
|
|
97
|
+
refetch: async () => {
|
|
98
|
+
await refetchSpy(customData);
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
render(_jsx(MyComponent, {}));
|
|
102
|
+
findByTestId(Button, 'refetchButton').trigger('onClick');
|
|
103
|
+
expect(refetchSpy).toHaveBeenCalledTimes(1);
|
|
104
|
+
expect(refetchSpy).toHaveBeenCalledWith(customData);
|
|
105
|
+
});
|
|
58
106
|
});
|
|
@@ -24,6 +24,8 @@ export const createMockHooks = () => {
|
|
|
24
24
|
properties,
|
|
25
25
|
error: null,
|
|
26
26
|
isLoading: false,
|
|
27
|
+
isRefetching: false,
|
|
28
|
+
refetch: async () => { },
|
|
27
29
|
};
|
|
28
30
|
},
|
|
29
31
|
useAssociations: (config) => {
|
|
@@ -45,6 +47,8 @@ export const createMockHooks = () => {
|
|
|
45
47
|
],
|
|
46
48
|
error: null,
|
|
47
49
|
isLoading: false,
|
|
50
|
+
isRefetching: false,
|
|
51
|
+
refetch: async () => { },
|
|
48
52
|
pagination: {
|
|
49
53
|
hasNextPage: false,
|
|
50
54
|
hasPreviousPage: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/ui-extensions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"./crm": "./dist/crm/index.js",
|
|
29
29
|
"./pages/home": "./dist/pages/home/index.js",
|
|
30
30
|
"./experimental": "./dist/experimental/index.js",
|
|
31
|
-
"./testing": "./dist/testing/index.js"
|
|
31
|
+
"./testing": "./dist/testing/index.js",
|
|
32
|
+
"./hs-internal": "./dist/hs-internal/index.js"
|
|
32
33
|
},
|
|
33
34
|
"license": "MIT",
|
|
34
35
|
"dependencies": {
|
|
@@ -74,5 +75,5 @@
|
|
|
74
75
|
"tsd": {
|
|
75
76
|
"directory": "src/__tests__/test-d"
|
|
76
77
|
},
|
|
77
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "c5b66da065a341df3afd98ce6641bb3e6317aeb4"
|
|
78
79
|
}
|