@hubspot/ui-extensions 0.11.0 → 0.11.2
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/__synced__/experimental/types.synced.d.ts +3 -4
- package/dist/__synced__/remoteComponents.synced.d.ts +168 -355
- package/dist/__synced__/remoteComponents.synced.js +186 -83
- package/dist/__synced__/types/components/button.synced.d.ts +6 -0
- package/dist/__synced__/types/components/index.synced.d.ts +38 -38
- package/dist/__synced__/types/index.synced.d.ts +7 -7
- package/dist/__synced__/types/index.synced.js +1 -9
- package/dist/__synced__/types/shared.synced.d.ts +2 -3
- package/dist/__synced__/utils/remote-component-registry.synced.d.ts +80 -0
- package/dist/__synced__/utils/remote-component-registry.synced.js +64 -0
- package/dist/__tests__/crm/hooks/useAssociations.spec.js +33 -29
- package/dist/__tests__/crm/hooks/useCrmProperties.spec.js +19 -18
- package/dist/__tests__/crm/utils/fetchAssociations.spec.js +8 -7
- package/dist/__tests__/crm/utils/fetchCrmProperties.spec.js +34 -33
- package/dist/crm/index.d.ts +1 -1
- package/dist/crm/index.js +1 -1
- package/dist/experimental/index.d.ts +1 -1
- package/dist/experimental/index.js +1 -1
- package/dist/experimental/testing/__tests__/debug.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/debug.spec.js +43 -0
- package/dist/experimental/testing/__tests__/find.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/find.spec.js +33 -0
- package/dist/experimental/testing/__tests__/findAll.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findAll.spec.js +12 -0
- package/dist/experimental/testing/__tests__/findAllChildren.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findAllChildren.spec.js +48 -0
- package/dist/experimental/testing/__tests__/findChild.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findChild.spec.js +29 -0
- package/dist/experimental/testing/__tests__/fragments.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/fragments.spec.js +59 -0
- package/dist/experimental/testing/__tests__/invalid-components.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/invalid-components.spec.js +88 -0
- package/dist/experimental/testing/__tests__/isMatch.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/isMatch.spec.js +60 -0
- package/dist/experimental/testing/__tests__/maybeFind.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/maybeFind.spec.js +58 -0
- package/dist/experimental/testing/__tests__/maybeFindChild.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/maybeFindChild.spec.js +65 -0
- package/dist/experimental/testing/__tests__/trigger.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/trigger.spec.js +40 -0
- package/dist/experimental/testing/__tests__/type-utils.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/type-utils.spec.js +163 -0
- package/dist/experimental/testing/__tests__/waitFor.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/waitFor.spec.js +55 -0
- package/dist/experimental/testing/index.d.ts +3 -0
- package/dist/experimental/testing/index.js +3 -0
- package/dist/experimental/testing/internal/constants.d.ts +2 -0
- package/dist/experimental/testing/internal/constants.js +1 -0
- package/dist/experimental/testing/internal/convert.d.ts +10 -0
- package/dist/experimental/testing/internal/convert.js +131 -0
- package/dist/experimental/testing/internal/debug.d.ts +8 -0
- package/dist/experimental/testing/internal/debug.js +19 -0
- package/dist/experimental/testing/internal/document.d.ts +14 -0
- package/dist/experimental/testing/internal/document.js +37 -0
- package/dist/experimental/testing/internal/element.d.ts +11 -0
- package/dist/experimental/testing/internal/element.js +67 -0
- package/dist/experimental/testing/internal/errors.d.ts +56 -0
- package/dist/experimental/testing/internal/errors.js +70 -0
- package/dist/experimental/testing/internal/fragment.d.ts +8 -0
- package/dist/experimental/testing/internal/fragment.js +44 -0
- package/dist/experimental/testing/internal/match.d.ts +19 -0
- package/dist/experimental/testing/internal/match.js +42 -0
- package/dist/experimental/testing/internal/print.d.ts +6 -0
- package/dist/experimental/testing/internal/print.js +114 -0
- package/dist/experimental/testing/internal/query.d.ts +57 -0
- package/dist/experimental/testing/internal/query.js +213 -0
- package/dist/experimental/testing/internal/root.d.ts +8 -0
- package/dist/experimental/testing/internal/root.js +44 -0
- package/dist/experimental/testing/internal/text.d.ts +9 -0
- package/dist/experimental/testing/internal/text.js +16 -0
- package/dist/experimental/testing/internal/utils/promise-utils.d.ts +14 -0
- package/dist/experimental/testing/internal/utils/promise-utils.js +14 -0
- package/dist/experimental/testing/render.d.ts +9 -0
- package/dist/experimental/testing/render.js +155 -0
- package/dist/experimental/testing/types.d.ts +2 -1
- package/dist/hubspot.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/pages/home/index.d.ts +1 -1
- package/dist/pages/home/index.js +1 -1
- package/package.json +19 -16
- package/dist/__synced__/appHomeRemoteComponents.synced.d.ts +0 -28
- package/dist/__synced__/appHomeRemoteComponents.synced.js +0 -21
- package/dist/__synced__/crmRemoteComponents.synced.d.ts +0 -66
- package/dist/__synced__/crmRemoteComponents.synced.js +0 -15
- package/dist/__synced__/experimentalRemoteComponents.synced.d.ts +0 -94
- package/dist/__synced__/experimentalRemoteComponents.synced.js +0 -56
- package/dist/coreComponents.d.ts +0 -848
- package/dist/coreComponents.js +0 -582
- package/dist/experimental/types.d.ts +0 -240
- package/dist/experimental/types.js +0 -5
- package/dist/types.d.ts +0 -3214
- package/dist/types.js +0 -244
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
1
2
|
// Set up the mock before importing the module
|
|
2
|
-
const mockFetchCrmProperties =
|
|
3
|
+
const mockFetchCrmProperties = vi.fn();
|
|
3
4
|
const mockSelf = {
|
|
4
5
|
fetchCrmProperties: mockFetchCrmProperties,
|
|
5
6
|
};
|
|
@@ -12,7 +13,7 @@ import { fetchCrmProperties } from '../../../crm/utils/fetchCrmProperties';
|
|
|
12
13
|
const DEFAULT_OPTIONS = {};
|
|
13
14
|
describe('fetchCrmProperties', () => {
|
|
14
15
|
beforeEach(() => {
|
|
15
|
-
|
|
16
|
+
vi.clearAllMocks();
|
|
16
17
|
});
|
|
17
18
|
it('successfully fetches CRM properties', async () => {
|
|
18
19
|
const mockApiResponse = {
|
|
@@ -20,15 +21,15 @@ describe('fetchCrmProperties', () => {
|
|
|
20
21
|
firstname: 'Test value for firstname',
|
|
21
22
|
lastname: 'Test value for lastname',
|
|
22
23
|
},
|
|
23
|
-
cleanup:
|
|
24
|
+
cleanup: vi.fn(),
|
|
24
25
|
};
|
|
25
26
|
const mockResponse = {
|
|
26
27
|
ok: true,
|
|
27
|
-
json:
|
|
28
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
28
29
|
};
|
|
29
30
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
30
31
|
const propertyNames = ['firstname', 'lastname'];
|
|
31
|
-
const result = await fetchCrmProperties(propertyNames,
|
|
32
|
+
const result = await fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS);
|
|
32
33
|
expect(mockFetchCrmProperties).toHaveBeenCalledWith(propertyNames, expect.any(Function), DEFAULT_OPTIONS);
|
|
33
34
|
expect(result).toEqual({
|
|
34
35
|
data: {
|
|
@@ -46,15 +47,15 @@ describe('fetchCrmProperties', () => {
|
|
|
46
47
|
email: 'john@example.com',
|
|
47
48
|
phone: null,
|
|
48
49
|
},
|
|
49
|
-
cleanup:
|
|
50
|
+
cleanup: vi.fn(),
|
|
50
51
|
};
|
|
51
52
|
const mockResponse = {
|
|
52
53
|
ok: true,
|
|
53
|
-
json:
|
|
54
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
54
55
|
};
|
|
55
56
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
56
57
|
const propertyNames = ['firstname', 'lastname', 'email', 'phone'];
|
|
57
|
-
const result = await fetchCrmProperties(propertyNames,
|
|
58
|
+
const result = await fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS);
|
|
58
59
|
expect(mockFetchCrmProperties).toHaveBeenCalledWith(propertyNames, expect.any(Function), DEFAULT_OPTIONS);
|
|
59
60
|
expect(result).toEqual({
|
|
60
61
|
data: {
|
|
@@ -70,29 +71,29 @@ describe('fetchCrmProperties', () => {
|
|
|
70
71
|
const mockResponse = {
|
|
71
72
|
ok: false,
|
|
72
73
|
statusText: 'Not Found',
|
|
73
|
-
json:
|
|
74
|
+
json: vi.fn().mockResolvedValue({}),
|
|
74
75
|
};
|
|
75
76
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
76
77
|
const propertyNames = ['firstname'];
|
|
77
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
78
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS)).rejects.toThrow('Failed to fetch CRM properties: Not Found');
|
|
78
79
|
});
|
|
79
80
|
it('throws an error when fetch fails', async () => {
|
|
80
81
|
mockFetchCrmProperties.mockRejectedValue(new Error('Network error'));
|
|
81
82
|
const propertyNames = ['firstname'];
|
|
82
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
83
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS)).rejects.toThrow('Network error');
|
|
83
84
|
});
|
|
84
85
|
it('throws an error if the response is not an object', async () => {
|
|
85
86
|
const mockApiResponse = {
|
|
86
87
|
data: 'Invalid response',
|
|
87
|
-
cleanup:
|
|
88
|
+
cleanup: vi.fn(),
|
|
88
89
|
};
|
|
89
90
|
const mockResponse = {
|
|
90
91
|
ok: true,
|
|
91
|
-
json:
|
|
92
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
92
93
|
};
|
|
93
94
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
94
95
|
const propertyNames = ['firstname'];
|
|
95
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
96
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS)).rejects.toThrow('Invalid response format');
|
|
96
97
|
});
|
|
97
98
|
it('throws an error if response contains invalid property values', async () => {
|
|
98
99
|
const mockApiResponse = {
|
|
@@ -101,15 +102,15 @@ describe('fetchCrmProperties', () => {
|
|
|
101
102
|
lastname: 123,
|
|
102
103
|
email: 'john@example.com',
|
|
103
104
|
},
|
|
104
|
-
cleanup:
|
|
105
|
+
cleanup: vi.fn(),
|
|
105
106
|
};
|
|
106
107
|
const mockResponse = {
|
|
107
108
|
ok: true,
|
|
108
|
-
json:
|
|
109
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
109
110
|
};
|
|
110
111
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
111
112
|
const propertyNames = ['firstname', 'lastname', 'email'];
|
|
112
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
113
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS)).rejects.toThrow('Invalid response format');
|
|
113
114
|
});
|
|
114
115
|
it('passes the propertiesUpdatedCallback and allows it to be called', async () => {
|
|
115
116
|
let capturedCallback;
|
|
@@ -118,18 +119,18 @@ describe('fetchCrmProperties', () => {
|
|
|
118
119
|
firstname: 'Initial',
|
|
119
120
|
lastname: 'Initial',
|
|
120
121
|
},
|
|
121
|
-
cleanup:
|
|
122
|
+
cleanup: vi.fn(),
|
|
122
123
|
};
|
|
123
124
|
const mockResponse = {
|
|
124
125
|
ok: true,
|
|
125
|
-
json:
|
|
126
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
126
127
|
};
|
|
127
128
|
mockFetchCrmProperties.mockImplementation((propertyNames, callback) => {
|
|
128
129
|
capturedCallback = callback;
|
|
129
130
|
return Promise.resolve(mockResponse);
|
|
130
131
|
});
|
|
131
132
|
const propertyNames = ['firstname', 'lastname'];
|
|
132
|
-
const mockCallback =
|
|
133
|
+
const mockCallback = vi.fn();
|
|
133
134
|
await fetchCrmProperties(propertyNames, mockCallback, DEFAULT_OPTIONS);
|
|
134
135
|
expect(typeof capturedCallback).toBe('function');
|
|
135
136
|
// Simulate the callback being called with new properties
|
|
@@ -146,18 +147,18 @@ describe('fetchCrmProperties', () => {
|
|
|
146
147
|
firstname: 'Initial',
|
|
147
148
|
lastname: null,
|
|
148
149
|
},
|
|
149
|
-
cleanup:
|
|
150
|
+
cleanup: vi.fn(),
|
|
150
151
|
};
|
|
151
152
|
const mockResponse = {
|
|
152
153
|
ok: true,
|
|
153
|
-
json:
|
|
154
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
154
155
|
};
|
|
155
156
|
mockFetchCrmProperties.mockImplementation((propertyNames, callback) => {
|
|
156
157
|
capturedCallback = callback;
|
|
157
158
|
return Promise.resolve(mockResponse);
|
|
158
159
|
});
|
|
159
160
|
const propertyNames = ['firstname', 'lastname'];
|
|
160
|
-
const mockCallback =
|
|
161
|
+
const mockCallback = vi.fn();
|
|
161
162
|
await fetchCrmProperties(propertyNames, mockCallback, DEFAULT_OPTIONS);
|
|
162
163
|
expect(typeof capturedCallback).toBe('function');
|
|
163
164
|
// Simulate the callback being called with new properties including null values
|
|
@@ -173,11 +174,11 @@ describe('fetchCrmProperties', () => {
|
|
|
173
174
|
firstname: 'John',
|
|
174
175
|
lastname: 'Doe',
|
|
175
176
|
},
|
|
176
|
-
cleanup:
|
|
177
|
+
cleanup: vi.fn(),
|
|
177
178
|
};
|
|
178
179
|
const mockResponse = {
|
|
179
180
|
ok: true,
|
|
180
|
-
json:
|
|
181
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
181
182
|
};
|
|
182
183
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
183
184
|
const propertyNames = ['firstname', 'lastname'];
|
|
@@ -192,7 +193,7 @@ describe('fetchCrmProperties', () => {
|
|
|
192
193
|
},
|
|
193
194
|
},
|
|
194
195
|
};
|
|
195
|
-
await fetchCrmProperties(propertyNames,
|
|
196
|
+
await fetchCrmProperties(propertyNames, vi.fn(), options);
|
|
196
197
|
expect(mockFetchCrmProperties).toHaveBeenCalledWith(propertyNames, expect.any(Function), options);
|
|
197
198
|
});
|
|
198
199
|
it('preserves error handling with formatting options', async () => {
|
|
@@ -206,27 +207,27 @@ describe('fetchCrmProperties', () => {
|
|
|
206
207
|
},
|
|
207
208
|
},
|
|
208
209
|
};
|
|
209
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
210
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), options)).rejects.toThrow('Network error');
|
|
210
211
|
expect(mockFetchCrmProperties).toHaveBeenCalledWith(propertyNames, expect.any(Function), options);
|
|
211
212
|
});
|
|
212
213
|
it('preserves response validation with formatting options', async () => {
|
|
213
214
|
const mockApiResponse = {
|
|
214
215
|
data: 'Invalid response',
|
|
215
|
-
cleanup:
|
|
216
|
+
cleanup: vi.fn(),
|
|
216
217
|
};
|
|
217
218
|
const mockResponse = {
|
|
218
219
|
ok: true,
|
|
219
|
-
json:
|
|
220
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
220
221
|
};
|
|
221
222
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
222
223
|
const propertyNames = ['firstname'];
|
|
223
224
|
const options = {
|
|
224
225
|
propertiesToFormat: 'all',
|
|
225
226
|
};
|
|
226
|
-
await expect(fetchCrmProperties(propertyNames,
|
|
227
|
+
await expect(fetchCrmProperties(propertyNames, vi.fn(), options)).rejects.toThrow('Invalid response format');
|
|
227
228
|
});
|
|
228
229
|
it('returns cleanup function that can be called', async () => {
|
|
229
|
-
const mockCleanup =
|
|
230
|
+
const mockCleanup = vi.fn();
|
|
230
231
|
const mockApiResponse = {
|
|
231
232
|
data: {
|
|
232
233
|
firstname: 'John',
|
|
@@ -235,11 +236,11 @@ describe('fetchCrmProperties', () => {
|
|
|
235
236
|
};
|
|
236
237
|
const mockResponse = {
|
|
237
238
|
ok: true,
|
|
238
|
-
json:
|
|
239
|
+
json: vi.fn().mockResolvedValue(mockApiResponse),
|
|
239
240
|
};
|
|
240
241
|
mockFetchCrmProperties.mockResolvedValue(mockResponse);
|
|
241
242
|
const propertyNames = ['firstname'];
|
|
242
|
-
const result = await fetchCrmProperties(propertyNames,
|
|
243
|
+
const result = await fetchCrmProperties(propertyNames, vi.fn(), DEFAULT_OPTIONS);
|
|
243
244
|
expect(result.cleanup).toBe(mockCleanup);
|
|
244
245
|
expect(typeof result.cleanup).toBe('function');
|
|
245
246
|
// Verify cleanup can be called without errors
|
package/dist/crm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../__synced__/
|
|
1
|
+
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../__synced__/remoteComponents.synced';
|
|
2
2
|
export { useCrmProperties } from './hooks/useCrmProperties';
|
|
3
3
|
export { useAssociations } from './hooks/useAssociations';
|
|
4
4
|
export type * from '../__synced__/types/crm.synced';
|
package/dist/crm/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../__synced__/
|
|
1
|
+
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../__synced__/remoteComponents.synced';
|
|
2
2
|
export { useCrmProperties } from './hooks/useCrmProperties';
|
|
3
3
|
export { useAssociations } from './hooks/useAssociations';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { useCrmProperties } from '../crm/hooks/useCrmProperties';
|
|
2
2
|
export { useAssociations } from '../crm/hooks/useAssociations';
|
|
3
|
-
export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/
|
|
3
|
+
export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/remoteComponents.synced';
|
|
4
4
|
export type * from '../__synced__/experimental/types.synced';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { useCrmProperties } from '../crm/hooks/useCrmProperties';
|
|
2
2
|
export { useAssociations } from '../crm/hooks/useAssociations';
|
|
3
|
-
export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/
|
|
3
|
+
export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/remoteComponents.synced';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow, List, Text } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
function MyComponent() {
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: _jsx(List, { children: _jsx(Text, { children: "Item 1" }) }), children: "Click me!" }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
7
|
+
}
|
|
8
|
+
describe('debugging', () => {
|
|
9
|
+
describe('toString', () => {
|
|
10
|
+
it('should allow the root node to be converted to a string', () => {
|
|
11
|
+
const { getRootNode } = render(_jsx(MyComponent, {}));
|
|
12
|
+
expect(getRootNode().toString()).toMatchSnapshot();
|
|
13
|
+
});
|
|
14
|
+
it('should allow a component node to be converted to a string', () => {
|
|
15
|
+
const { find } = render(_jsx(MyComponent, {}));
|
|
16
|
+
expect(find(Button).toString()).toMatchSnapshot();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('debugLog()', () => {
|
|
20
|
+
let consoleLogSpy;
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
23
|
+
});
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
consoleLogSpy.mockRestore();
|
|
26
|
+
});
|
|
27
|
+
it('should allow debug logging the root node', () => {
|
|
28
|
+
const { debugLog } = render(_jsx(MyComponent, {}));
|
|
29
|
+
debugLog('MY COMPONENT TREE');
|
|
30
|
+
expect(consoleLogSpy.mock.calls).toMatchSnapshot();
|
|
31
|
+
});
|
|
32
|
+
it('should allow debug logging a component element node', () => {
|
|
33
|
+
const { find } = render(_jsx(MyComponent, {}));
|
|
34
|
+
find(Button).debugLog('MY BUTTON');
|
|
35
|
+
expect(consoleLogSpy.mock.calls).toMatchSnapshot();
|
|
36
|
+
});
|
|
37
|
+
it('should allow debug logging a component element node without a label', () => {
|
|
38
|
+
const { find } = render(_jsx(MyComponent, {}));
|
|
39
|
+
find(Button).debugLog();
|
|
40
|
+
expect(consoleLogSpy.mock.calls).toMatchSnapshot();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow, Text } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
import { ComponentNotFoundError, FindInvalidComponentError, } from '../internal/errors';
|
|
6
|
+
describe('find()', () => {
|
|
7
|
+
it('should allow assertions against initial rendered output', () => {
|
|
8
|
+
const buttonLabel = 'Click me!';
|
|
9
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
10
|
+
const button = find(Button);
|
|
11
|
+
expect(button.props).toEqual({ variant: 'primary' });
|
|
12
|
+
expect(button.text).toEqual(buttonLabel);
|
|
13
|
+
});
|
|
14
|
+
it('should allow finding a matching component based on props object', () => {
|
|
15
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" })] }));
|
|
16
|
+
const primaryButton = find(Button, { variant: 'primary' });
|
|
17
|
+
expect(primaryButton.props).toMatchObject({ variant: 'primary' });
|
|
18
|
+
});
|
|
19
|
+
it('should allow finding a matching component based on a predicate function', () => {
|
|
20
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" })] }));
|
|
21
|
+
const primaryButton = find(Button, (node) => node.props.variant === 'primary');
|
|
22
|
+
expect(primaryButton.props).toMatchObject({ variant: 'primary' });
|
|
23
|
+
});
|
|
24
|
+
it('should throw an error when no match is found', () => {
|
|
25
|
+
const { find } = render(_jsx(Alert, { title: "My Alert" }));
|
|
26
|
+
expect(() => find(Text)).toThrow(ComponentNotFoundError);
|
|
27
|
+
});
|
|
28
|
+
it('should throw an error when target component is invalid', () => {
|
|
29
|
+
const { find } = render(_jsx(Alert, { title: "My Alert" }));
|
|
30
|
+
const MyFakeComponent = () => { };
|
|
31
|
+
expect(() => find(MyFakeComponent)).toThrow(FindInvalidComponentError);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
describe('findAll()', () => {
|
|
6
|
+
it('should allow finding all matching components', () => {
|
|
7
|
+
const { findAll } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" })] }));
|
|
8
|
+
const buttons = findAll(Button);
|
|
9
|
+
expect(buttons[0]?.props).toMatchObject({ variant: 'secondary' });
|
|
10
|
+
expect(buttons[1]?.props).toMatchObject({ variant: 'primary' });
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow, Text } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
describe('findAllChildren()', () => {
|
|
6
|
+
it('should allow finding all direct children from the root node', () => {
|
|
7
|
+
const { findAllChildren } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" }), _jsx(Alert, { title: "Another Alert" })] }));
|
|
8
|
+
const alerts = findAllChildren(Alert);
|
|
9
|
+
expect(alerts).toHaveLength(2);
|
|
10
|
+
expect(alerts[0]?.props).toMatchObject({ title: 'My Alert' });
|
|
11
|
+
expect(alerts[1]?.props).toMatchObject({ title: 'Another Alert' });
|
|
12
|
+
});
|
|
13
|
+
it('should only find direct children, not nested descendants', () => {
|
|
14
|
+
const { findAllChildren } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" })] }));
|
|
15
|
+
const buttons = findAllChildren(Button);
|
|
16
|
+
expect(buttons).toHaveLength(0);
|
|
17
|
+
});
|
|
18
|
+
it('should allow finding all direct children from a nested component', () => {
|
|
19
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" })] }), _jsx(Alert, { title: "My Alert" })] }));
|
|
20
|
+
const buttonRow = find(ButtonRow);
|
|
21
|
+
const buttons = buttonRow.findAllChildren(Button);
|
|
22
|
+
expect(buttons).toHaveLength(2);
|
|
23
|
+
expect(buttons[0]?.props).toMatchObject({ variant: 'secondary' });
|
|
24
|
+
expect(buttons[1]?.props).toMatchObject({ variant: 'primary' });
|
|
25
|
+
});
|
|
26
|
+
it('should return empty array when no direct children match', () => {
|
|
27
|
+
const { findAllChildren } = render(_jsx(_Fragment, { children: _jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: "Button 1" }) }) }));
|
|
28
|
+
const texts = findAllChildren(Text);
|
|
29
|
+
expect(texts).toHaveLength(0);
|
|
30
|
+
});
|
|
31
|
+
it('should support matcher function', () => {
|
|
32
|
+
const { find } = render(_jsx(_Fragment, { children: _jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" }), _jsx(Button, { variant: "secondary", children: "Button 3" })] }) }));
|
|
33
|
+
const buttonRow = find(ButtonRow);
|
|
34
|
+
const secondaryButtons = buttonRow.findAllChildren(Button, (node) => node.props.variant === 'secondary');
|
|
35
|
+
expect(secondaryButtons).toHaveLength(2);
|
|
36
|
+
expect(secondaryButtons[0]?.props).toMatchObject({ variant: 'secondary' });
|
|
37
|
+
expect(secondaryButtons[1]?.props).toMatchObject({ variant: 'secondary' });
|
|
38
|
+
});
|
|
39
|
+
it('should support matcher object', () => {
|
|
40
|
+
const { find } = render(_jsx(_Fragment, { children: _jsxs(ButtonRow, { children: [_jsx(Button, { variant: "secondary", children: "Button 1" }), _jsx(Button, { variant: "primary", children: "Button 2" }), _jsx(Button, { variant: "secondary", children: "Button 3" })] }) }));
|
|
41
|
+
const buttonRow = find(ButtonRow);
|
|
42
|
+
const primaryButtons = buttonRow.findAllChildren(Button, {
|
|
43
|
+
variant: 'primary',
|
|
44
|
+
});
|
|
45
|
+
expect(primaryButtons).toHaveLength(1);
|
|
46
|
+
expect(primaryButtons[0]?.props).toMatchObject({ variant: 'primary' });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
import { ComponentNotFoundError, FindInvalidComponentError, } from '../internal/errors';
|
|
6
|
+
describe('findChild()', () => {
|
|
7
|
+
it('should allow finding a child from the root node', () => {
|
|
8
|
+
const buttonLabel = '';
|
|
9
|
+
const { findChild } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
10
|
+
expect(findChild(ButtonRow)).toBeDefined();
|
|
11
|
+
});
|
|
12
|
+
it('should allow finding a child from a nested component', () => {
|
|
13
|
+
const buttonLabel = '';
|
|
14
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
15
|
+
const buttonRow = find(ButtonRow);
|
|
16
|
+
expect(buttonRow.findChild(Button).props).toEqual({ variant: 'primary' });
|
|
17
|
+
});
|
|
18
|
+
it('should throw an error when no match is found', () => {
|
|
19
|
+
const { find } = render(_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: "Click me!" }) }));
|
|
20
|
+
const buttonRow = find(ButtonRow);
|
|
21
|
+
expect(() => buttonRow.findChild(Alert)).toThrow(ComponentNotFoundError);
|
|
22
|
+
});
|
|
23
|
+
it('should throw an error when target component is invalid', () => {
|
|
24
|
+
const { find } = render(_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: "Click me!" }) }));
|
|
25
|
+
const MyFakeComponent = () => { };
|
|
26
|
+
const buttonRow = find(ButtonRow);
|
|
27
|
+
expect(() => buttonRow.findChild(MyFakeComponent)).toThrow(FindInvalidComponentError);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Alert, Button, ButtonRow, List, Text } from '../../../index';
|
|
4
|
+
import { render } from '../index';
|
|
5
|
+
import { InvalidFragmentPropArrayError } from '../internal/errors';
|
|
6
|
+
describe('fragments', () => {
|
|
7
|
+
it('should allow assertions against components with fragment props', () => {
|
|
8
|
+
const buttonLabel = 'Click me!';
|
|
9
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: _jsx(List, { children: _jsx(Text, { children: "Item 1" }) }), children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
10
|
+
expect(find(Text).text).toEqual('Item 1');
|
|
11
|
+
expect(find(Button).text).toEqual(buttonLabel);
|
|
12
|
+
});
|
|
13
|
+
it('should handle undefined fragment props', () => {
|
|
14
|
+
const buttonLabel = 'Click me!';
|
|
15
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
16
|
+
const button = find(Button);
|
|
17
|
+
const { props: buttonProps } = button;
|
|
18
|
+
expect(buttonProps.overlay).toBeUndefined();
|
|
19
|
+
expect(find(Alert).props).toEqual({ title: 'My Alert' });
|
|
20
|
+
});
|
|
21
|
+
it('should handle null fragment props', () => {
|
|
22
|
+
const buttonLabel = 'Click me!';
|
|
23
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: null, children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
24
|
+
const button = find(Button);
|
|
25
|
+
const { props: buttonProps } = button;
|
|
26
|
+
expect(buttonProps.overlay?.children).toHaveLength(0);
|
|
27
|
+
expect(find(Alert).props).toEqual({ title: 'My Alert' });
|
|
28
|
+
});
|
|
29
|
+
it('should throw an error if an array fragment prop is passed', () => {
|
|
30
|
+
const buttonLabel = 'Click me!';
|
|
31
|
+
const arrayProp = [1, 2, 3];
|
|
32
|
+
expect(() => {
|
|
33
|
+
render(_jsx(Button, { variant: "primary", overlay: arrayProp, children: buttonLabel }));
|
|
34
|
+
}).toThrow(InvalidFragmentPropArrayError);
|
|
35
|
+
});
|
|
36
|
+
it('should handle string fragment props', () => {
|
|
37
|
+
const buttonLabel = 'Click me!';
|
|
38
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: "My Overlay", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
39
|
+
const button = find(Button);
|
|
40
|
+
expect(button.props.overlay?.text).toEqual('My Overlay');
|
|
41
|
+
expect(find(Alert).props).toEqual({ title: 'My Alert' });
|
|
42
|
+
});
|
|
43
|
+
it('should handle fragment props that are a JSX fragment', () => {
|
|
44
|
+
const buttonLabel = 'Click me!';
|
|
45
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: _jsx(_Fragment, { children: "My Overlay" }), children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
46
|
+
const button = find(Button);
|
|
47
|
+
expect(button.props.overlay?.text).toEqual('My Overlay');
|
|
48
|
+
expect(find(Alert).props).toEqual({ title: 'My Alert' });
|
|
49
|
+
});
|
|
50
|
+
it('should allow assertions against fragments rendered by a custom component', () => {
|
|
51
|
+
const buttonLabel = 'Click me!';
|
|
52
|
+
function MyOverlay() {
|
|
53
|
+
return (_jsx(List, { children: _jsx(Text, { children: "Item 1" }) }));
|
|
54
|
+
}
|
|
55
|
+
const { find } = render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: _jsx(MyOverlay, {}), children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
56
|
+
expect(find(Text).text).toEqual('Item 1');
|
|
57
|
+
expect(find(Button).text).toEqual(buttonLabel);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { Alert, Button, ButtonRow, Text } from '../../../index';
|
|
5
|
+
import { render } from '../index';
|
|
6
|
+
import { InvalidComponentsError } from '../internal/errors';
|
|
7
|
+
import { createDeferred } from '../internal/utils/promise-utils';
|
|
8
|
+
const setTimeoutPromise = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9
|
+
describe('handling invalid components', () => {
|
|
10
|
+
it('should throw an error if initial render contains invalid components', () => {
|
|
11
|
+
function MyComponent() {
|
|
12
|
+
return (_jsx("div", { children: _jsx("span", { children: _jsx(Button, { variant: "primary", children: "Click me!" }) }) }));
|
|
13
|
+
}
|
|
14
|
+
expect(() => render(_jsx(MyComponent, {}))).toThrow(InvalidComponentsError);
|
|
15
|
+
let errorMessage;
|
|
16
|
+
try {
|
|
17
|
+
render(_jsx(MyComponent, {}));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
errorMessage = String(error);
|
|
21
|
+
}
|
|
22
|
+
expect(errorMessage).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
|
+
it('should throw an error if initial render contains invalid components inside a fragment', () => {
|
|
25
|
+
function MyComponent() {
|
|
26
|
+
return (_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", overlay: _jsx("div", { children: "Overlay" }), children: "Click me!" }) }), _jsx(Alert, { title: "My Alert" })] }));
|
|
27
|
+
}
|
|
28
|
+
expect(() => render(_jsx(MyComponent, {}))).toThrow(InvalidComponentsError);
|
|
29
|
+
});
|
|
30
|
+
it('should throw an error if triggering an event results in an invalid component to be rendered', () => {
|
|
31
|
+
function Counter() {
|
|
32
|
+
const [count, setCount] = useState(0);
|
|
33
|
+
const handleClick = () => {
|
|
34
|
+
setCount(count + 1);
|
|
35
|
+
};
|
|
36
|
+
return (_jsx(Button, { variant: "primary", onClick: handleClick, children: count === 0 ? 'Click me!' : _jsxs("div", { children: ["Clicked ", count, " times"] }) }));
|
|
37
|
+
}
|
|
38
|
+
const { find } = render(_jsx(Counter, {}));
|
|
39
|
+
expect(find(Button).text).toEqual('Click me!');
|
|
40
|
+
// Should throw an error because the component is invalid
|
|
41
|
+
expect(() => {
|
|
42
|
+
find(Button).trigger('onClick');
|
|
43
|
+
}).toThrow(InvalidComponentsError);
|
|
44
|
+
});
|
|
45
|
+
it('should throw an error if the component is invalid after an asynchronous update', async () => {
|
|
46
|
+
function AsyncCounter() {
|
|
47
|
+
const [count, setCount] = useState(0);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
setCount((currentCount) => currentCount + 1);
|
|
51
|
+
}, 10);
|
|
52
|
+
}, []);
|
|
53
|
+
return (_jsx(Button, { children: count === 0 ? 'Click me!' : _jsxs("div", { children: ["Clicked ", count, " times"] }) }));
|
|
54
|
+
}
|
|
55
|
+
const { find, waitFor } = render(_jsx(AsyncCounter, {}));
|
|
56
|
+
expect(find(Button).text).toEqual('Click me!');
|
|
57
|
+
await expect(waitFor(() => {
|
|
58
|
+
expect(find(Button).text).toEqual('Clicked 1 times');
|
|
59
|
+
})).rejects.toThrow(InvalidComponentsError);
|
|
60
|
+
});
|
|
61
|
+
it('should throw an error if the component is invalid after an asynchronous update when not using waitFor', async () => {
|
|
62
|
+
const usePromise = (promise) => {
|
|
63
|
+
const [isPending, setIsPending] = useState(true);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
setIsPending(true);
|
|
66
|
+
promise
|
|
67
|
+
.then(() => setIsPending(false))
|
|
68
|
+
.catch(() => setIsPending(false));
|
|
69
|
+
}, [promise]);
|
|
70
|
+
return { isPending };
|
|
71
|
+
};
|
|
72
|
+
function AsyncCounter({ promise }) {
|
|
73
|
+
const { isPending } = usePromise(promise);
|
|
74
|
+
if (isPending) {
|
|
75
|
+
return _jsx(Text, { children: "Loading..." });
|
|
76
|
+
}
|
|
77
|
+
return _jsx("div", { children: "Loaded!" });
|
|
78
|
+
}
|
|
79
|
+
const loadingDeferred = createDeferred();
|
|
80
|
+
const { find } = render(_jsx(AsyncCounter, { promise: loadingDeferred.promise }));
|
|
81
|
+
expect(find(Text).text).toEqual('Loading...');
|
|
82
|
+
loadingDeferred.resolve();
|
|
83
|
+
await setTimeoutPromise(0);
|
|
84
|
+
expect(() => {
|
|
85
|
+
find(Button);
|
|
86
|
+
}).toThrow(InvalidComponentsError);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|