@hubspot/ui-extensions 0.11.2 → 0.11.4

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 (215) hide show
  1. package/dist/__tests__/crm/hooks/useAssociations.spec.js +4 -4
  2. package/dist/__tests__/crm/hooks/useCrmProperties.spec.js +2 -2
  3. package/dist/__tests__/crm/utils/fetchAssociations.spec.js +5 -5
  4. package/dist/__tests__/crm/utils/fetchCrmProperties.spec.js +4 -4
  5. package/dist/clientTypes.d.ts +1 -0
  6. package/dist/clientTypes.js +1 -1
  7. package/dist/crm/hooks/useAssociations.d.ts +5 -3
  8. package/dist/crm/hooks/useAssociations.js +4 -2
  9. package/dist/crm/hooks/useCrmProperties.d.ts +4 -2
  10. package/dist/crm/hooks/useCrmProperties.js +4 -2
  11. package/dist/crm/index.d.ts +4 -4
  12. package/dist/crm/index.js +3 -3
  13. package/dist/crm/utils/fetchAssociations.d.ts +1 -1
  14. package/dist/experimental/index.d.ts +4 -4
  15. package/dist/experimental/index.js +3 -3
  16. package/dist/experimental/testing/__tests__/createRenderer.spec.js +23 -0
  17. package/dist/experimental/testing/__tests__/debug.spec.js +21 -7
  18. package/dist/experimental/testing/__tests__/find.spec.js +23 -8
  19. package/dist/experimental/testing/__tests__/findAll.spec.js +4 -3
  20. package/dist/experimental/testing/__tests__/findAllChildren.spec.js +14 -8
  21. package/dist/experimental/testing/__tests__/findByTestId.spec.js +126 -0
  22. package/dist/experimental/testing/__tests__/findChild.spec.js +11 -7
  23. package/dist/experimental/testing/__tests__/fragments.spec.js +17 -10
  24. package/dist/experimental/testing/__tests__/invalid-components.spec.js +16 -8
  25. package/dist/experimental/testing/__tests__/isMatch.spec.js +106 -53
  26. package/dist/experimental/testing/__tests__/logger.spec.js +10 -0
  27. package/dist/experimental/testing/__tests__/maybeFind.spec.js +20 -11
  28. package/dist/experimental/testing/__tests__/maybeFindByTestId.spec.js +65 -0
  29. package/dist/experimental/testing/__tests__/maybeFindChild.spec.js +22 -12
  30. package/dist/experimental/testing/__tests__/mocks.actions.spec.js +19 -0
  31. package/dist/experimental/testing/__tests__/mocks.context.spec.js +24 -0
  32. package/dist/experimental/testing/__tests__/mocks.runServerlessFunction.spec.js +35 -0
  33. package/dist/experimental/testing/__tests__/mocks.useAssociations.spec.js +47 -0
  34. package/dist/experimental/testing/__tests__/mocks.useCrmProperties.spec.js +58 -0
  35. package/dist/experimental/testing/__tests__/props.spec.js +13 -0
  36. package/dist/experimental/testing/__tests__/testId.spec.js +18 -0
  37. package/dist/experimental/testing/__tests__/trigger.spec.js +9 -6
  38. package/dist/experimental/testing/__tests__/type-utils.spec.js +12 -10
  39. package/dist/experimental/testing/__tests__/waitFor.spec.js +7 -5
  40. package/dist/experimental/testing/index.d.ts +4 -3
  41. package/dist/experimental/testing/index.js +4 -3
  42. package/dist/experimental/testing/internal/constants.d.ts +2 -2
  43. package/dist/experimental/testing/internal/constants.js +1 -1
  44. package/dist/experimental/testing/internal/convert.d.ts +2 -2
  45. package/dist/experimental/testing/internal/convert.js +42 -24
  46. package/dist/experimental/testing/internal/debug.d.ts +3 -3
  47. package/dist/experimental/testing/internal/debug.js +4 -5
  48. package/dist/experimental/testing/internal/document.d.ts +1 -1
  49. package/dist/experimental/testing/internal/document.js +4 -1
  50. package/dist/experimental/testing/internal/element.d.ts +4 -3
  51. package/dist/experimental/testing/internal/element.js +15 -10
  52. package/dist/experimental/testing/internal/errors.d.ts +45 -2
  53. package/dist/experimental/testing/internal/errors.js +44 -2
  54. package/dist/experimental/testing/internal/fragment.d.ts +3 -2
  55. package/dist/experimental/testing/internal/fragment.js +13 -9
  56. package/dist/experimental/testing/internal/match.d.ts +3 -12
  57. package/dist/experimental/testing/internal/match.js +0 -23
  58. package/dist/experimental/testing/internal/mocks/index.d.ts +17 -0
  59. package/dist/experimental/testing/internal/mocks/index.js +46 -0
  60. package/dist/experimental/testing/internal/mocks/mock-extension-point-api.d.ts +2 -0
  61. package/dist/experimental/testing/internal/mocks/mock-extension-point-api.js +166 -0
  62. package/dist/experimental/testing/internal/mocks/mock-hooks.d.ts +2 -0
  63. package/dist/experimental/testing/internal/mocks/mock-hooks.js +59 -0
  64. package/dist/experimental/testing/internal/print.d.ts +2 -2
  65. package/dist/experimental/testing/internal/print.js +17 -11
  66. package/dist/experimental/testing/internal/query.d.ts +19 -9
  67. package/dist/experimental/testing/internal/query.js +91 -28
  68. package/dist/experimental/testing/internal/root.d.ts +1 -1
  69. package/dist/experimental/testing/internal/root.js +12 -8
  70. package/dist/experimental/testing/internal/text.d.ts +3 -2
  71. package/dist/experimental/testing/internal/text.js +12 -3
  72. package/dist/experimental/testing/internal/type-utils-internal.d.ts +44 -0
  73. package/dist/experimental/testing/internal/type-utils-internal.js +54 -0
  74. package/dist/experimental/testing/internal/types-internal.d.ts +20 -2
  75. package/dist/experimental/testing/render.d.ts +32 -6
  76. package/dist/experimental/testing/render.js +96 -32
  77. package/dist/experimental/testing/type-utils.d.ts +2 -2
  78. package/dist/experimental/testing/type-utils.js +1 -1
  79. package/dist/experimental/testing/types.d.ts +127 -10
  80. package/dist/experimental/testing/utils.d.ts +11 -0
  81. package/dist/experimental/testing/utils.js +24 -0
  82. package/dist/hubspot.d.ts +2 -4
  83. package/dist/hubspot.js +3 -3
  84. package/dist/index.d.ts +5 -5
  85. package/dist/index.js +5 -5
  86. package/dist/internal/global-utils.d.ts +6 -0
  87. package/dist/internal/global-utils.js +37 -0
  88. package/dist/internal/hook-utils.d.ts +19 -0
  89. package/dist/internal/hook-utils.js +34 -0
  90. package/dist/logger.d.ts +1 -8
  91. package/dist/logger.js +3 -2
  92. package/dist/pages/home/index.d.ts +1 -1
  93. package/dist/pages/home/index.js +1 -1
  94. package/dist/{__synced__/remoteComponents.synced.d.ts → shared/remoteComponents.d.ts} +103 -103
  95. package/dist/{__synced__/remoteComponents.synced.js → shared/remoteComponents.js} +1 -1
  96. package/dist/{__synced__/types/components/accordion.synced.d.ts → shared/types/components/accordion.d.ts} +2 -2
  97. package/dist/{__synced__/types/components/alert.synced.d.ts → shared/types/components/alert.d.ts} +2 -1
  98. package/dist/{__synced__/types/components/app-home-header-actions.synced.d.ts → shared/types/components/app-home-header-actions.d.ts} +4 -4
  99. package/dist/{__synced__/types/components/button-row.synced.d.ts → shared/types/components/button-row.d.ts} +2 -2
  100. package/dist/{__synced__/types/components/button.synced.d.ts → shared/types/components/button.d.ts} +3 -3
  101. package/dist/{__synced__/types/components/card.synced.d.ts → shared/types/components/card.d.ts} +2 -1
  102. package/dist/{__synced__/types/components/chart.synced.d.ts → shared/types/components/chart.d.ts} +2 -1
  103. package/dist/{__synced__/types/components/description-list.synced.d.ts → shared/types/components/description-list.d.ts} +3 -2
  104. package/dist/{__synced__/types/components/divider.synced.d.ts → shared/types/components/divider.d.ts} +2 -2
  105. package/dist/{__synced__/types/components/dropdown.synced.d.ts → shared/types/components/dropdown.d.ts} +5 -5
  106. package/dist/{__synced__/types/components/empty-state.synced.d.ts → shared/types/components/empty-state.d.ts} +2 -1
  107. package/dist/{__synced__/types/components/error-state.synced.d.ts → shared/types/components/error-state.d.ts} +2 -1
  108. package/dist/{__synced__/types/components/form.synced.d.ts → shared/types/components/form.d.ts} +3 -3
  109. package/dist/{__synced__/types/components/heading.synced.d.ts → shared/types/components/heading.d.ts} +2 -1
  110. package/dist/{__synced__/types/components/icon.synced.d.ts → shared/types/components/icon.d.ts} +2 -2
  111. package/dist/{__synced__/types/components/iframe.synced.d.ts → shared/types/components/iframe.d.ts} +2 -2
  112. package/dist/{__synced__/types/components/illustration.synced.d.ts → shared/types/components/illustration.d.ts} +2 -1
  113. package/dist/{__synced__/types/components/image.synced.d.ts → shared/types/components/image.d.ts} +3 -3
  114. package/dist/shared/types/components/index.d.ts +38 -0
  115. package/dist/{__synced__/types/components/inputs.synced.d.ts → shared/types/components/inputs.d.ts} +2 -1
  116. package/dist/{__synced__/types/components/layouts.synced.d.ts → shared/types/components/layouts.d.ts} +6 -6
  117. package/dist/{__synced__/types/components/link.synced.d.ts → shared/types/components/link.d.ts} +3 -3
  118. package/dist/{__synced__/types/components/list.synced.d.ts → shared/types/components/list.d.ts} +2 -1
  119. package/dist/{__synced__/types/components/loading-spinner.synced.d.ts → shared/types/components/loading-spinner.d.ts} +2 -2
  120. package/dist/{__synced__/types/components/modal.synced.d.ts → shared/types/components/modal.d.ts} +4 -4
  121. package/dist/{__synced__/types/components/panel.synced.d.ts → shared/types/components/panel.d.ts} +5 -5
  122. package/dist/{__synced__/types/components/progress-bar.synced.d.ts → shared/types/components/progress-bar.d.ts} +2 -1
  123. package/dist/{__synced__/types/components/selects.synced.d.ts → shared/types/components/selects.d.ts} +2 -1
  124. package/dist/{__synced__/types/components/statistics.synced.d.ts → shared/types/components/statistics.d.ts} +4 -3
  125. package/dist/{__synced__/types/components/status-tag.synced.d.ts → shared/types/components/status-tag.d.ts} +2 -1
  126. package/dist/{__synced__/types/components/step-indicator.synced.d.ts → shared/types/components/step-indicator.d.ts} +2 -2
  127. package/dist/{__synced__/types/components/table.synced.d.ts → shared/types/components/table.d.ts} +5 -4
  128. package/dist/shared/types/components/table.js +1 -0
  129. package/dist/{__synced__/types/components/tabs.synced.d.ts → shared/types/components/tabs.d.ts} +3 -2
  130. package/dist/shared/types/components/tabs.js +1 -0
  131. package/dist/{__synced__/types/components/tag.synced.d.ts → shared/types/components/tag.d.ts} +3 -3
  132. package/dist/shared/types/components/tag.js +1 -0
  133. package/dist/{__synced__/types/components/text.synced.d.ts → shared/types/components/text.d.ts} +2 -1
  134. package/dist/shared/types/components/text.js +1 -0
  135. package/dist/{__synced__/types/components/tile.synced.d.ts → shared/types/components/tile.d.ts} +2 -1
  136. package/dist/shared/types/components/tile.js +1 -0
  137. package/dist/{__synced__/types/components/toggle.synced.d.ts → shared/types/components/toggle.d.ts} +2 -2
  138. package/dist/shared/types/components/toggle.js +1 -0
  139. package/dist/{__synced__/types/components/toggleInputs.synced.d.ts → shared/types/components/toggleInputs.d.ts} +4 -4
  140. package/dist/shared/types/components/toggleInputs.js +1 -0
  141. package/dist/{__synced__/types/components/tooltip.synced.d.ts → shared/types/components/tooltip.d.ts} +2 -1
  142. package/dist/shared/types/components/tooltip.js +1 -0
  143. package/dist/{__synced__/types/context.synced.d.ts → shared/types/context.d.ts} +1 -1
  144. package/dist/shared/types/context.js +1 -0
  145. package/dist/{__synced__/types/crm.synced.d.ts → shared/types/crm.d.ts} +13 -13
  146. package/dist/shared/types/crm.js +1 -0
  147. package/dist/{__synced__/experimental/types.synced.d.ts → shared/types/experimental.d.ts} +10 -14
  148. package/dist/shared/types/experimental.js +1 -0
  149. package/dist/shared/types/extend.d.ts +4 -0
  150. package/dist/shared/types/extend.js +1 -0
  151. package/dist/{__synced__/types/extension-points.synced.d.ts → shared/types/extension-points.d.ts} +18 -10
  152. package/dist/{__synced__/types/http-requests.synced.d.ts → shared/types/http-requests.d.ts} +1 -1
  153. package/dist/shared/types/index.d.ts +8 -0
  154. package/dist/shared/types/index.js +1 -0
  155. package/dist/shared/types/logger.d.ts +7 -0
  156. package/dist/shared/types/logger.js +1 -0
  157. package/dist/shared/types/reactions.js +1 -0
  158. package/dist/{__synced__/types/shared.synced.d.ts → shared/types/shared.d.ts} +3 -0
  159. package/dist/shared/types/worker-globals.d.ts +17 -0
  160. package/dist/shared/types/worker-globals.js +1 -0
  161. package/dist/{__synced__/utils/remote-component-registry.synced.d.ts → shared/utils/remote-component-registry.d.ts} +1 -1
  162. package/dist/{__synced__/utils/remote-component-registry.synced.js → shared/utils/remote-component-registry.js} +0 -1
  163. package/package.json +6 -4
  164. package/dist/__synced__/experimental/types.synced.js +0 -5
  165. package/dist/__synced__/types/components/index.synced.d.ts +0 -38
  166. package/dist/__synced__/types/index.synced.d.ts +0 -8
  167. package/dist/__synced__/types/index.synced.js +0 -1
  168. /package/dist/{__synced__/types/actions.synced.js → experimental/testing/__tests__/createRenderer.spec.d.ts} +0 -0
  169. /package/dist/{__synced__/types/components/accordion.synced.js → experimental/testing/__tests__/findByTestId.spec.d.ts} +0 -0
  170. /package/dist/{__synced__/types/components/alert.synced.js → experimental/testing/__tests__/logger.spec.d.ts} +0 -0
  171. /package/dist/{__synced__/types/components/app-home-header-actions.synced.js → experimental/testing/__tests__/maybeFindByTestId.spec.d.ts} +0 -0
  172. /package/dist/{__synced__/types/components/button-row.synced.js → experimental/testing/__tests__/mocks.actions.spec.d.ts} +0 -0
  173. /package/dist/{__synced__/types/components/button.synced.js → experimental/testing/__tests__/mocks.context.spec.d.ts} +0 -0
  174. /package/dist/{__synced__/types/components/card.synced.js → experimental/testing/__tests__/mocks.runServerlessFunction.spec.d.ts} +0 -0
  175. /package/dist/{__synced__/types/components/description-list.synced.js → experimental/testing/__tests__/mocks.useAssociations.spec.d.ts} +0 -0
  176. /package/dist/{__synced__/types/components/divider.synced.js → experimental/testing/__tests__/mocks.useCrmProperties.spec.d.ts} +0 -0
  177. /package/dist/{__synced__/types/components/dropdown.synced.js → experimental/testing/__tests__/props.spec.d.ts} +0 -0
  178. /package/dist/{__synced__/types/components/empty-state.synced.js → experimental/testing/__tests__/testId.spec.d.ts} +0 -0
  179. /package/dist/{__synced__/types/actions.synced.d.ts → shared/types/actions.d.ts} +0 -0
  180. /package/dist/{__synced__/types/components/error-state.synced.js → shared/types/actions.js} +0 -0
  181. /package/dist/{__synced__/types/components/form.synced.js → shared/types/components/accordion.js} +0 -0
  182. /package/dist/{__synced__/types/components/heading.synced.js → shared/types/components/alert.js} +0 -0
  183. /package/dist/{__synced__/types/components/icon.synced.js → shared/types/components/app-home-header-actions.js} +0 -0
  184. /package/dist/{__synced__/types/components/iframe.synced.js → shared/types/components/button-row.js} +0 -0
  185. /package/dist/{__synced__/types/components/image.synced.js → shared/types/components/button.js} +0 -0
  186. /package/dist/{__synced__/types/components/index.synced.js → shared/types/components/card.js} +0 -0
  187. /package/dist/{__synced__/types/components/chart.synced.js → shared/types/components/chart.js} +0 -0
  188. /package/dist/{__synced__/types/components/inputs.synced.js → shared/types/components/description-list.js} +0 -0
  189. /package/dist/{__synced__/types/components/layouts.synced.js → shared/types/components/divider.js} +0 -0
  190. /package/dist/{__synced__/types/components/link.synced.js → shared/types/components/dropdown.js} +0 -0
  191. /package/dist/{__synced__/types/components/list.synced.js → shared/types/components/empty-state.js} +0 -0
  192. /package/dist/{__synced__/types/components/loading-spinner.synced.js → shared/types/components/error-state.js} +0 -0
  193. /package/dist/{__synced__/types/components/modal.synced.js → shared/types/components/form.js} +0 -0
  194. /package/dist/{__synced__/types/components/panel.synced.js → shared/types/components/heading.js} +0 -0
  195. /package/dist/{__synced__/types/components/progress-bar.synced.js → shared/types/components/icon.js} +0 -0
  196. /package/dist/{__synced__/types/components/selects.synced.js → shared/types/components/iframe.js} +0 -0
  197. /package/dist/{__synced__/types/components/illustration.synced.js → shared/types/components/illustration.js} +0 -0
  198. /package/dist/{__synced__/types/components/statistics.synced.js → shared/types/components/image.js} +0 -0
  199. /package/dist/{__synced__/types/components/status-tag.synced.js → shared/types/components/index.js} +0 -0
  200. /package/dist/{__synced__/types/components/step-indicator.synced.js → shared/types/components/inputs.js} +0 -0
  201. /package/dist/{__synced__/types/components/table.synced.js → shared/types/components/layouts.js} +0 -0
  202. /package/dist/{__synced__/types/components/tabs.synced.js → shared/types/components/link.js} +0 -0
  203. /package/dist/{__synced__/types/components/tag.synced.js → shared/types/components/list.js} +0 -0
  204. /package/dist/{__synced__/types/components/text.synced.js → shared/types/components/loading-spinner.js} +0 -0
  205. /package/dist/{__synced__/types/components/tile.synced.js → shared/types/components/modal.js} +0 -0
  206. /package/dist/{__synced__/types/components/toggle.synced.js → shared/types/components/panel.js} +0 -0
  207. /package/dist/{__synced__/types/components/toggleInputs.synced.js → shared/types/components/progress-bar.js} +0 -0
  208. /package/dist/{__synced__/types/components/tooltip.synced.js → shared/types/components/selects.js} +0 -0
  209. /package/dist/{__synced__/types/context.synced.js → shared/types/components/statistics.js} +0 -0
  210. /package/dist/{__synced__/types/crm.synced.js → shared/types/components/status-tag.js} +0 -0
  211. /package/dist/{__synced__/types/reactions.synced.js → shared/types/components/step-indicator.js} +0 -0
  212. /package/dist/{__synced__/types/extension-points.synced.js → shared/types/extension-points.js} +0 -0
  213. /package/dist/{__synced__/types/http-requests.synced.js → shared/types/http-requests.js} +0 -0
  214. /package/dist/{__synced__/types/reactions.synced.d.ts → shared/types/reactions.d.ts} +0 -0
  215. /package/dist/{__synced__/types/shared.synced.js → shared/types/shared.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { renderHook, waitFor } from '@testing-library/react';
2
2
  import { vi } from 'vitest';
3
- import { useAssociations } from '../../../crm/hooks/useAssociations';
4
- import { fetchAssociations } from '../../../crm/utils/fetchAssociations';
3
+ import { useAssociations } from "../../../crm/hooks/useAssociations.js";
4
+ import { fetchAssociations } from "../../../crm/utils/fetchAssociations.js";
5
5
  // Mock the logger module
6
6
  vi.mock('../../../logger', () => ({
7
7
  logger: {
@@ -12,7 +12,7 @@ vi.mock('../../../logger', () => ({
12
12
  },
13
13
  }));
14
14
  // Mock the fetchAssociations function, keep utility functions
15
- vi.mock('../../../crm/utils/fetchAssociations', async (importOriginal) => {
15
+ vi.mock('../../../crm/utils/fetchAssociations.ts', async (importOriginal) => {
16
16
  const actual = (await importOriginal());
17
17
  return {
18
18
  ...actual,
@@ -278,7 +278,7 @@ describe('useAssociations with Pagination', () => {
278
278
  mockFetchAssociations.mockResolvedValue({
279
279
  data: {
280
280
  results: [],
281
- hasMore: false,
281
+ hasMore: false, // No more pages
282
282
  nextOffset: 10,
283
283
  },
284
284
  cleanup: vi.fn(),
@@ -1,7 +1,7 @@
1
1
  import { renderHook, waitFor } from '@testing-library/react';
2
2
  import { vi } from 'vitest';
3
- import { useCrmProperties } from '../../../crm/hooks/useCrmProperties';
4
- import * as fetchCrmPropertiesModule from '../../../crm/utils/fetchCrmProperties';
3
+ import { useCrmProperties } from "../../../crm/hooks/useCrmProperties.js";
4
+ import * as fetchCrmPropertiesModule from "../../../crm/utils/fetchCrmProperties.js";
5
5
  // Mock the logger module
6
6
  vi.mock('../../../logger', () => ({
7
7
  logger: {
@@ -9,7 +9,7 @@ Object.defineProperty(global, 'self', {
9
9
  value: mockSelf,
10
10
  writable: true,
11
11
  });
12
- import { fetchAssociations, calculatePaginationFlags, } from '../../../crm/utils/fetchAssociations';
12
+ import { fetchAssociations, calculatePaginationFlags, } from "../../../crm/utils/fetchAssociations.js";
13
13
  describe('fetchAssociations', () => {
14
14
  // Helper functions
15
15
  const createMockResponse = (data, overrides = {}) => ({
@@ -62,7 +62,7 @@ describe('fetchAssociations', () => {
62
62
  ];
63
63
  const mockData = {
64
64
  results: mockResults,
65
- hasMore: offset < 200,
65
+ hasMore: offset < 200, // Has more until offset 200
66
66
  nextOffset: offset + pageLength,
67
67
  };
68
68
  return Promise.resolve(createMockResponse(mockData));
@@ -211,7 +211,7 @@ describe('fetchAssociations', () => {
211
211
  });
212
212
  it('should handle different object types', async () => {
213
213
  const request = createBasicRequest({
214
- toObjectType: '0-2',
214
+ toObjectType: '0-2', // Company
215
215
  properties: ['name'],
216
216
  });
217
217
  const result = await fetchAssociations(request);
@@ -251,7 +251,7 @@ describe('fetchAssociations', () => {
251
251
  });
252
252
  it('should throw error for invalid association result structure', async () => {
253
253
  const invalidData = {
254
- results: [{ invalidStructure: true }],
254
+ results: [{ invalidStructure: true }], // missing required fields
255
255
  hasMore: false,
256
256
  nextOffset: 0,
257
257
  };
@@ -264,7 +264,7 @@ describe('fetchAssociations', () => {
264
264
  results: [
265
265
  {
266
266
  toObjectId: 1000,
267
- associationTypes: 'not an array',
267
+ associationTypes: 'not an array', // should be array
268
268
  properties: {},
269
269
  },
270
270
  ],
@@ -9,7 +9,7 @@ Object.defineProperty(global, 'self', {
9
9
  value: mockSelf,
10
10
  writable: true,
11
11
  });
12
- import { fetchCrmProperties } from '../../../crm/utils/fetchCrmProperties';
12
+ import { fetchCrmProperties } from "../../../crm/utils/fetchCrmProperties.js";
13
13
  const DEFAULT_OPTIONS = {};
14
14
  describe('fetchCrmProperties', () => {
15
15
  beforeEach(() => {
@@ -84,7 +84,7 @@ describe('fetchCrmProperties', () => {
84
84
  });
85
85
  it('throws an error if the response is not an object', async () => {
86
86
  const mockApiResponse = {
87
- data: 'Invalid response',
87
+ data: 'Invalid response', // data should be an object
88
88
  cleanup: vi.fn(),
89
89
  };
90
90
  const mockResponse = {
@@ -99,7 +99,7 @@ describe('fetchCrmProperties', () => {
99
99
  const mockApiResponse = {
100
100
  data: {
101
101
  firstname: 'John',
102
- lastname: 123,
102
+ lastname: 123, // Invalid: should be string or null
103
103
  email: 'john@example.com',
104
104
  },
105
105
  cleanup: vi.fn(),
@@ -212,7 +212,7 @@ describe('fetchCrmProperties', () => {
212
212
  });
213
213
  it('preserves response validation with formatting options', async () => {
214
214
  const mockApiResponse = {
215
- data: 'Invalid response',
215
+ data: 'Invalid response', // data should be an object
216
216
  cleanup: vi.fn(),
217
217
  };
218
218
  const mockResponse = {
@@ -38,3 +38,4 @@ declare module '*?inline' {
38
38
  const src: string;
39
39
  export default src;
40
40
  }
41
+ export {};
@@ -1 +1 @@
1
- "use strict";
1
+ export {};
@@ -1,5 +1,5 @@
1
- import { type FetchAssociationsRequest, type AssociationResult } from '../utils/fetchAssociations';
2
- import { type FetchCrmPropertiesOptions } from '../utils/fetchCrmProperties';
1
+ import { type FetchAssociationsRequest, type AssociationResult } from '../utils/fetchAssociations.ts';
2
+ import { type FetchCrmPropertiesOptions } from '../utils/fetchCrmProperties.ts';
3
3
  export interface UseAssociationsOptions {
4
4
  propertiesToFormat?: 'all' | string[];
5
5
  formattingOptions?: FetchCrmPropertiesOptions['formattingOptions'];
@@ -22,4 +22,6 @@ export interface UseAssociationsResult {
22
22
  /**
23
23
  * A hook to fetch and manage associations between CRM objects with pagination support.
24
24
  */
25
- export declare function useAssociations(config: Omit<FetchAssociationsRequest, 'offset'>, options?: UseAssociationsOptions): UseAssociationsResult;
25
+ declare function useAssociationsInternal(config: Omit<FetchAssociationsRequest, 'offset'>, options?: UseAssociationsOptions): UseAssociationsResult;
26
+ export declare const useAssociations: typeof useAssociationsInternal;
27
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useReducer, useMemo, useRef, useCallback } from 'react';
2
- import { fetchAssociations, DEFAULT_PAGE_SIZE, calculatePaginationFlags, } from '../utils/fetchAssociations';
2
+ import { fetchAssociations, DEFAULT_PAGE_SIZE, calculatePaginationFlags, } from "../utils/fetchAssociations.js";
3
+ import { createMockAwareHook } from "../../internal/hook-utils.js";
3
4
  function createInitialState(pageSize) {
4
5
  return {
5
6
  results: [],
@@ -82,7 +83,7 @@ const DEFAULT_OPTIONS = {};
82
83
  /**
83
84
  * A hook to fetch and manage associations between CRM objects with pagination support.
84
85
  */
85
- export function useAssociations(config, options = DEFAULT_OPTIONS) {
86
+ function useAssociationsInternal(config, options = DEFAULT_OPTIONS) {
86
87
  const pageSize = config?.pageLength ?? DEFAULT_PAGE_SIZE;
87
88
  const [state, dispatch] = useReducer(associationsReducer, useMemo(() => createInitialState(pageSize), [pageSize]));
88
89
  /**
@@ -202,3 +203,4 @@ export function useAssociations(config, options = DEFAULT_OPTIONS) {
202
203
  },
203
204
  };
204
205
  }
206
+ export const useAssociations = createMockAwareHook('useAssociations', useAssociationsInternal);
@@ -1,4 +1,4 @@
1
- import { type FetchCrmPropertiesOptions } from '../utils/fetchCrmProperties';
1
+ import { type FetchCrmPropertiesOptions } from '../utils/fetchCrmProperties.ts';
2
2
  export interface CrmPropertiesState {
3
3
  properties: Record<string, string | null>;
4
4
  error: Error | null;
@@ -7,4 +7,6 @@ export interface CrmPropertiesState {
7
7
  /**
8
8
  * A hook for using and managing CRM properties.
9
9
  */
10
- export declare function useCrmProperties(propertyNames: string[], options?: FetchCrmPropertiesOptions): CrmPropertiesState;
10
+ declare function useCrmPropertiesInternal(propertyNames: string[], options?: FetchCrmPropertiesOptions): CrmPropertiesState;
11
+ export declare const useCrmProperties: typeof useCrmPropertiesInternal;
12
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useReducer, useMemo, useRef } from 'react';
2
- import { fetchCrmProperties, } from '../utils/fetchCrmProperties';
2
+ import { fetchCrmProperties, } from "../utils/fetchCrmProperties.js";
3
+ import { createMockAwareHook } from "../../internal/hook-utils.js";
3
4
  const initialState = {
4
5
  properties: {},
5
6
  error: null,
@@ -35,7 +36,7 @@ const DEFAULT_OPTIONS = {};
35
36
  /**
36
37
  * A hook for using and managing CRM properties.
37
38
  */
38
- export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
39
+ function useCrmPropertiesInternal(propertyNames, options = DEFAULT_OPTIONS) {
39
40
  const [state, dispatch] = useReducer(crmPropertiesReducer, initialState);
40
41
  /**
41
42
  * HOOK OPTIMIZATION:
@@ -107,3 +108,4 @@ export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
107
108
  }, [stablePropertyNames, stableOptions]);
108
109
  return state;
109
110
  }
111
+ export const useCrmProperties = createMockAwareHook('useCrmProperties', useCrmPropertiesInternal);
@@ -1,4 +1,4 @@
1
- export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../__synced__/remoteComponents.synced';
2
- export { useCrmProperties } from './hooks/useCrmProperties';
3
- export { useAssociations } from './hooks/useAssociations';
4
- export type * from '../__synced__/types/crm.synced';
1
+ export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from '../shared/remoteComponents.tsx';
2
+ export { useCrmProperties } from './hooks/useCrmProperties.ts';
3
+ export { useAssociations } from './hooks/useAssociations.ts';
4
+ export type * from '../shared/types/crm.ts';
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__/remoteComponents.synced';
2
- export { useCrmProperties } from './hooks/useCrmProperties';
3
- export { useAssociations } from './hooks/useAssociations';
1
+ export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from "../shared/remoteComponents.js";
2
+ export { useCrmProperties } from "./hooks/useCrmProperties.js";
3
+ export { useAssociations } from "./hooks/useAssociations.js";
@@ -1,4 +1,4 @@
1
- import { FetchCrmPropertiesOptions } from './fetchCrmProperties';
1
+ import { FetchCrmPropertiesOptions } from './fetchCrmProperties.ts';
2
2
  export declare const DEFAULT_PAGE_SIZE = 10;
3
3
  /**
4
4
  * Calculate pagination flags based on current page and API hasMore flag
@@ -1,4 +1,4 @@
1
- export { useCrmProperties } from '../crm/hooks/useCrmProperties';
2
- export { useAssociations } from '../crm/hooks/useAssociations';
3
- export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/remoteComponents.synced';
4
- export type * from '../__synced__/experimental/types.synced';
1
+ export { useCrmProperties } from '../crm/hooks/useCrmProperties.ts';
2
+ export { useAssociations } from '../crm/hooks/useAssociations.ts';
3
+ export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../shared/remoteComponents.tsx';
4
+ export type * from '../shared/types/experimental.ts';
@@ -1,3 +1,3 @@
1
- export { useCrmProperties } from '../crm/hooks/useCrmProperties';
2
- export { useAssociations } from '../crm/hooks/useAssociations';
3
- export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from '../__synced__/remoteComponents.synced';
1
+ export { useCrmProperties } from "../crm/hooks/useCrmProperties.js";
2
+ export { useAssociations } from "../crm/hooks/useAssociations.js";
3
+ export { Iframe, MediaObject, Stack2, Center, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, } from "../shared/remoteComponents.js";
@@ -0,0 +1,23 @@
1
+ import { InvalidExtensionPointLocationError } from "../internal/errors.js";
2
+ import { createRenderer } from "../render.js";
3
+ describe('createRenderer', () => {
4
+ it('should create a renderer object', () => {
5
+ const renderer = createRenderer('crm.record.tab');
6
+ expect(renderer.render).toBeTypeOf('function');
7
+ });
8
+ it('should throw an error for an invalid extension point location', () => {
9
+ expect(() => {
10
+ createRenderer('INVALID_LOCATION');
11
+ }).toThrow(new InvalidExtensionPointLocationError('INVALID_LOCATION'));
12
+ });
13
+ it('should throw an error for an invalid extension point location with a helpful error message', () => {
14
+ let errorMessage;
15
+ try {
16
+ createRenderer('INVALID_LOCATION');
17
+ }
18
+ catch (error) {
19
+ errorMessage = String(error);
20
+ }
21
+ expect(errorMessage).toBe(`InvalidExtensionPointLocationError: Invalid extension point location of "INVALID_LOCATION". Allowed locations are: "crm.preview", "crm.record.sidebar", "crm.record.tab", "helpdesk.sidebar", "uie.playground.middle", "settings", "home"`);
22
+ });
23
+ });
@@ -1,18 +1,20 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { describe, expect, it } from 'vitest';
3
- import { Alert, Button, ButtonRow, List, Text } from '../../../index';
4
- import { render } from '../index';
3
+ import { Alert, Button, ButtonRow, List, Text } from "../../../index.js";
4
+ import { createRenderer, isRenderedTextNode } from "../index.js";
5
5
  function MyComponent() {
6
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
7
  }
8
8
  describe('debugging', () => {
9
9
  describe('toString', () => {
10
10
  it('should allow the root node to be converted to a string', () => {
11
- const { getRootNode } = render(_jsx(MyComponent, {}));
11
+ const { render, getRootNode } = createRenderer('crm.record.tab');
12
+ render(_jsx(MyComponent, {}));
12
13
  expect(getRootNode().toString()).toMatchSnapshot();
13
14
  });
14
15
  it('should allow a component node to be converted to a string', () => {
15
- const { find } = render(_jsx(MyComponent, {}));
16
+ const { render, find } = createRenderer('crm.record.tab');
17
+ render(_jsx(MyComponent, {}));
16
18
  expect(find(Button).toString()).toMatchSnapshot();
17
19
  });
18
20
  });
@@ -25,19 +27,31 @@ describe('debugging', () => {
25
27
  consoleLogSpy.mockRestore();
26
28
  });
27
29
  it('should allow debug logging the root node', () => {
28
- const { debugLog } = render(_jsx(MyComponent, {}));
30
+ const { render, debugLog } = createRenderer('crm.record.tab');
31
+ render(_jsx(MyComponent, {}));
29
32
  debugLog('MY COMPONENT TREE');
30
33
  expect(consoleLogSpy.mock.calls).toMatchSnapshot();
31
34
  });
32
35
  it('should allow debug logging a component element node', () => {
33
- const { find } = render(_jsx(MyComponent, {}));
36
+ const { render, find } = createRenderer('crm.record.tab');
37
+ render(_jsx(MyComponent, {}));
34
38
  find(Button).debugLog('MY BUTTON');
35
39
  expect(consoleLogSpy.mock.calls).toMatchSnapshot();
36
40
  });
37
41
  it('should allow debug logging a component element node without a label', () => {
38
- const { find } = render(_jsx(MyComponent, {}));
42
+ const { render, find } = createRenderer('crm.record.tab');
43
+ render(_jsx(MyComponent, {}));
39
44
  find(Button).debugLog();
40
45
  expect(consoleLogSpy.mock.calls).toMatchSnapshot();
41
46
  });
47
+ it('should allow debug logging a text node', () => {
48
+ const { render, find } = createRenderer('crm.record.tab');
49
+ render(_jsx(MyComponent, {}));
50
+ const buttonNode = find(Button);
51
+ const textNode = buttonNode.childNodes[0];
52
+ expect(isRenderedTextNode(textNode)).toBe(true);
53
+ textNode.debugLog('MY TEXT LABEL');
54
+ expect(consoleLogSpy.mock.calls).toMatchSnapshot();
55
+ });
42
56
  });
43
57
  });
@@ -1,33 +1,48 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
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';
3
+ import { Alert, Button, ButtonRow, Text } from "../../../index.js";
4
+ import { createRenderer } from "../index.js";
5
+ import { ComponentNotFoundError, FindInvalidComponentError, } from "../internal/errors.js";
6
6
  describe('find()', () => {
7
7
  it('should allow assertions against initial rendered output', () => {
8
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" })] }));
9
+ const { render, find } = createRenderer('crm.record.tab');
10
+ render(_jsxs(_Fragment, { children: [_jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: buttonLabel }) }), _jsx(Alert, { title: "My Alert" })] }));
10
11
  const button = find(Button);
11
12
  expect(button.props).toEqual({ variant: 'primary' });
12
13
  expect(button.text).toEqual(buttonLabel);
13
14
  });
14
15
  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 { render, find } = createRenderer('crm.record.tab');
17
+ 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
18
  const primaryButton = find(Button, { variant: 'primary' });
17
19
  expect(primaryButton.props).toMatchObject({ variant: 'primary' });
18
20
  });
19
21
  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" })] }));
22
+ const { render, find } = createRenderer('crm.record.tab');
23
+ 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
24
  const primaryButton = find(Button, (node) => node.props.variant === 'primary');
22
25
  expect(primaryButton.props).toMatchObject({ variant: 'primary' });
23
26
  });
24
27
  it('should throw an error when no match is found', () => {
25
- const { find } = render(_jsx(Alert, { title: "My Alert" }));
28
+ const { render, find } = createRenderer('crm.record.tab');
29
+ render(_jsx(Alert, { title: "My Alert" }));
26
30
  expect(() => find(Text)).toThrow(ComponentNotFoundError);
27
31
  });
28
32
  it('should throw an error when target component is invalid', () => {
29
- const { find } = render(_jsx(Alert, { title: "My Alert" }));
33
+ const { render, find } = createRenderer('crm.record.tab');
34
+ render(_jsx(Alert, { title: "My Alert" }));
30
35
  const MyFakeComponent = () => { };
31
36
  expect(() => find(MyFakeComponent)).toThrow(FindInvalidComponentError);
32
37
  });
38
+ it('should allow re-rendering and finding a matching component', () => {
39
+ const { render, find, maybeFind } = createRenderer('crm.record.tab');
40
+ render(_jsx(Alert, { title: "My Alert" }));
41
+ const alert = find(Alert);
42
+ expect(alert.props).toEqual({ title: 'My Alert' });
43
+ render(_jsx(Button, { variant: "primary", children: "Click me!" }));
44
+ const button = find(Button);
45
+ expect(button.props).toEqual({ variant: 'primary' });
46
+ expect(maybeFind(Alert)).toBeNull(); // The Alert should be gone now since we re-rendered.
47
+ });
33
48
  });
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { describe, expect, it } from 'vitest';
3
- import { Alert, Button, ButtonRow } from '../../../index';
4
- import { render } from '../index';
3
+ import { Alert, Button, ButtonRow } from "../../../index.js";
4
+ import { createRenderer } from "../index.js";
5
5
  describe('findAll()', () => {
6
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" })] }));
7
+ const { render, findAll } = createRenderer('crm.record.tab');
8
+ 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
9
  const buttons = findAll(Button);
9
10
  expect(buttons[0]?.props).toMatchObject({ variant: 'secondary' });
10
11
  expect(buttons[1]?.props).toMatchObject({ variant: 'primary' });
@@ -1,22 +1,25 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { describe, expect, it } from 'vitest';
3
- import { Alert, Button, ButtonRow, Text } from '../../../index';
4
- import { render } from '../index';
3
+ import { Alert, Button, ButtonRow, Text } from "../../../index.js";
4
+ import { createRenderer } from "../index.js";
5
5
  describe('findAllChildren()', () => {
6
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" })] }));
7
+ const { render, findAllChildren } = createRenderer('crm.record.tab');
8
+ 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
9
  const alerts = findAllChildren(Alert);
9
10
  expect(alerts).toHaveLength(2);
10
11
  expect(alerts[0]?.props).toMatchObject({ title: 'My Alert' });
11
12
  expect(alerts[1]?.props).toMatchObject({ title: 'Another Alert' });
12
13
  });
13
14
  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 { render, findAllChildren } = createRenderer('crm.record.tab');
16
+ 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
17
  const buttons = findAllChildren(Button);
16
18
  expect(buttons).toHaveLength(0);
17
19
  });
18
20
  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" })] }));
21
+ const { render, find } = createRenderer('crm.record.tab');
22
+ 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
23
  const buttonRow = find(ButtonRow);
21
24
  const buttons = buttonRow.findAllChildren(Button);
22
25
  expect(buttons).toHaveLength(2);
@@ -24,12 +27,14 @@ describe('findAllChildren()', () => {
24
27
  expect(buttons[1]?.props).toMatchObject({ variant: 'primary' });
25
28
  });
26
29
  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" }) }) }));
30
+ const { render, findAllChildren } = createRenderer('crm.record.tab');
31
+ render(_jsx(_Fragment, { children: _jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", children: "Button 1" }) }) }));
28
32
  const texts = findAllChildren(Text);
29
33
  expect(texts).toHaveLength(0);
30
34
  });
31
35
  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" })] }) }));
36
+ const { render, find } = createRenderer('crm.record.tab');
37
+ 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
38
  const buttonRow = find(ButtonRow);
34
39
  const secondaryButtons = buttonRow.findAllChildren(Button, (node) => node.props.variant === 'secondary');
35
40
  expect(secondaryButtons).toHaveLength(2);
@@ -37,7 +42,8 @@ describe('findAllChildren()', () => {
37
42
  expect(secondaryButtons[1]?.props).toMatchObject({ variant: 'secondary' });
38
43
  });
39
44
  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" })] }) }));
45
+ const { render, find } = createRenderer('crm.record.tab');
46
+ 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
47
  const buttonRow = find(ButtonRow);
42
48
  const primaryButtons = buttonRow.findAllChildren(Button, {
43
49
  variant: 'primary',
@@ -0,0 +1,126 @@
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.js";
4
+ import { createRenderer } from "../index.js";
5
+ import { ComponentMismatchedByTestIdError, ComponentNotFoundByTestIdError, FindInvalidComponentError, } from "../internal/errors.js";
6
+ describe('findByTestId()', () => {
7
+ it('should find a component by testId', () => {
8
+ const { render, findByTestId } = createRenderer('crm.record.tab');
9
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", testId: "primary-button", children: "Click me" }) }));
10
+ const button = findByTestId(Button, 'primary-button');
11
+ expect(button.props).toMatchObject({
12
+ variant: 'primary',
13
+ testId: 'primary-button',
14
+ });
15
+ expect(button.text).toEqual('Click me');
16
+ });
17
+ it('should find a component by testId among multiple components', () => {
18
+ const { render, findByTestId } = createRenderer('crm.record.tab');
19
+ render(_jsxs(_Fragment, { children: [_jsx(Button, { variant: "secondary", testId: "button-1", children: "Button 1" }), _jsx(Button, { variant: "primary", testId: "button-2", children: "Button 2" }), _jsx(Button, { variant: "destructive", testId: "button-3", children: "Button 3" })] }));
20
+ const button = findByTestId(Button, 'button-2');
21
+ expect(button.props).toMatchObject({
22
+ variant: 'primary',
23
+ testId: 'button-2',
24
+ });
25
+ expect(button.text).toEqual('Button 2');
26
+ });
27
+ it('should find a nested component by testId', () => {
28
+ const { render, findByTestId } = createRenderer('crm.record.tab');
29
+ render(_jsx(_Fragment, { children: _jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", testId: "nested-button", children: "Nested Button" }) }) }));
30
+ const button = findByTestId(Button, 'nested-button');
31
+ expect(button.props).toMatchObject({
32
+ variant: 'primary',
33
+ testId: 'nested-button',
34
+ });
35
+ expect(button.text).toEqual('Nested Button');
36
+ });
37
+ it('should find different component types by their testIds', () => {
38
+ const { render, findByTestId } = createRenderer('crm.record.tab');
39
+ render(_jsxs(_Fragment, { children: [_jsx(Button, { variant: "primary", testId: "my-button", children: "Click me" }), _jsx(Alert, { title: "My Alert", testId: "my-alert" })] }));
40
+ const button = findByTestId(Button, 'my-button');
41
+ expect(button.props).toMatchObject({
42
+ variant: 'primary',
43
+ testId: 'my-button',
44
+ });
45
+ const alert = findByTestId(Alert, 'my-alert');
46
+ expect(alert.props).toMatchObject({
47
+ title: 'My Alert',
48
+ testId: 'my-alert',
49
+ });
50
+ });
51
+ it('should throw ComponentNotFoundByTestIdError when testId is not found', () => {
52
+ const { render, findByTestId } = createRenderer('crm.record.tab');
53
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", testId: "existing-button", children: "Click me" }) }));
54
+ expect(() => findByTestId(Button, 'non-existent-testid')).toThrow(ComponentNotFoundByTestIdError);
55
+ });
56
+ it('should throw ComponentNotFoundByTestIdError when component has no testId', () => {
57
+ const { render, findByTestId } = createRenderer('crm.record.tab');
58
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", children: "Click me" }) }));
59
+ expect(() => findByTestId(Button, 'some-testid')).toThrow(ComponentNotFoundByTestIdError);
60
+ });
61
+ it('should throw ComponentNotFoundByTestIdError with a helpful message when component has no testId', () => {
62
+ const { render, findByTestId } = createRenderer('crm.record.tab');
63
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", children: "Click me" }) }));
64
+ let error = null;
65
+ try {
66
+ findByTestId(Button, 'some-testid');
67
+ }
68
+ catch (_error) {
69
+ error = _error;
70
+ }
71
+ expect(error).toBeInstanceOf(ComponentNotFoundByTestIdError);
72
+ expect(error?.message).toMatchSnapshot();
73
+ });
74
+ it('should throw ComponentMismatchedByTestIdError when testId exists but component type does not match', () => {
75
+ const { render, findByTestId } = createRenderer('crm.record.tab');
76
+ render(_jsxs(_Fragment, { children: [_jsx(Button, { variant: "primary", testId: "my-element", children: "Click me" }), _jsx(Alert, { title: "My Alert", testId: "my-alert" })] }));
77
+ expect(() => findByTestId(Alert, 'my-element')).toThrow(ComponentMismatchedByTestIdError);
78
+ });
79
+ it('should throw FindInvalidComponentError when target component is invalid', () => {
80
+ const { render, findByTestId } = createRenderer('crm.record.tab');
81
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", testId: "my-button", children: "Click me" }) }));
82
+ const MyFakeComponent = () => { };
83
+ expect(() => findByTestId(MyFakeComponent, 'my-button')).toThrow(FindInvalidComponentError);
84
+ });
85
+ it('should work after re-rendering with new components', () => {
86
+ const { render, findByTestId } = createRenderer('crm.record.tab');
87
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "primary", testId: "button-1", children: "Button 1" }) }));
88
+ let button = findByTestId(Button, 'button-1');
89
+ expect(button.text).toEqual('Button 1');
90
+ render(_jsx(_Fragment, { children: _jsx(Button, { variant: "secondary", testId: "button-2", children: "Button 2" }) }));
91
+ button = findByTestId(Button, 'button-2');
92
+ expect(button.text).toEqual('Button 2');
93
+ expect(() => findByTestId(Button, 'button-1')).toThrow(ComponentNotFoundByTestIdError);
94
+ });
95
+ it('should handle testIds with special characters', () => {
96
+ const { render, findByTestId } = createRenderer('crm.record.tab');
97
+ render(_jsxs(_Fragment, { children: [_jsx(Button, { variant: "primary", testId: "button-with-dashes-123", children: "Button 1" }), _jsx(Button, { variant: "secondary", testId: "button_with_underscores", children: "Button 2" }), _jsx(Button, { variant: "destructive", testId: "button.with.dots", children: "Button 3" })] }));
98
+ const button1 = findByTestId(Button, 'button-with-dashes-123');
99
+ expect(button1.props.variant).toEqual('primary');
100
+ const button2 = findByTestId(Button, 'button_with_underscores');
101
+ expect(button2.props.variant).toEqual('secondary');
102
+ const button3 = findByTestId(Button, 'button.with.dots');
103
+ expect(button3.props.variant).toEqual('destructive');
104
+ });
105
+ it('should work with deeply nested components', () => {
106
+ const { render, findByTestId } = createRenderer('crm.record.tab');
107
+ render(_jsx(_Fragment, { children: _jsx(ButtonRow, { children: _jsx(ButtonRow, { children: _jsx(ButtonRow, { children: _jsx(Button, { variant: "primary", testId: "deeply-nested", children: "Deep Button" }) }) }) }) }));
108
+ const button = findByTestId(Button, 'deeply-nested');
109
+ expect(button.props).toMatchObject({
110
+ variant: 'primary',
111
+ testId: 'deeply-nested',
112
+ });
113
+ });
114
+ it('should find component by testId regardless of rendering order', () => {
115
+ const { render, findByTestId } = createRenderer('crm.record.tab');
116
+ render(_jsxs(_Fragment, { children: [_jsx(Text, { testId: "text-1", children: "First" }), _jsx(Button, { variant: "primary", testId: "button-1", children: "Button" }), _jsx(Alert, { title: "Alert", testId: "alert-1" }), _jsx(Text, { testId: "text-2", children: "Second" })] }));
117
+ const button = findByTestId(Button, 'button-1');
118
+ expect(button.props.variant).toEqual('primary');
119
+ const text1 = findByTestId(Text, 'text-1');
120
+ expect(text1.text).toEqual('First');
121
+ const text2 = findByTestId(Text, 'text-2');
122
+ expect(text2.text).toEqual('Second');
123
+ const alert = findByTestId(Alert, 'alert-1');
124
+ expect(alert.props.title).toEqual('Alert');
125
+ });
126
+ });