@getmicdrop/svelte-components 5.5.4 → 5.5.5

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 (290) hide show
  1. package/dist/calendar/AboutShow/AboutShow.spec.d.ts +2 -0
  2. package/dist/calendar/AboutShow/AboutShow.spec.d.ts.map +1 -0
  3. package/dist/calendar/AboutShow/AboutShow.spec.js +791 -0
  4. package/dist/calendar/Calendar/MiniMonthCalendar.spec.d.ts +2 -0
  5. package/dist/calendar/Calendar/MiniMonthCalendar.spec.d.ts.map +1 -0
  6. package/dist/calendar/Calendar/MiniMonthCalendar.spec.js +1191 -0
  7. package/dist/calendar/FAQs/FAQs.spec.d.ts +2 -0
  8. package/dist/calendar/FAQs/FAQs.spec.d.ts.map +1 -0
  9. package/dist/calendar/FAQs/FAQs.spec.js +238 -0
  10. package/dist/calendar/MonthSwitcher/MonthSwitcher.spec.d.ts +2 -0
  11. package/dist/calendar/MonthSwitcher/MonthSwitcher.spec.d.ts.map +1 -0
  12. package/dist/calendar/MonthSwitcher/MonthSwitcher.spec.js +420 -0
  13. package/dist/calendar/OrderSummary/OrderSummary.spec.d.ts +2 -0
  14. package/dist/calendar/OrderSummary/OrderSummary.spec.d.ts.map +1 -0
  15. package/dist/calendar/OrderSummary/OrderSummary.spec.js +808 -0
  16. package/dist/calendar/PublicCard/PublicCard.spec.d.ts +2 -0
  17. package/dist/calendar/PublicCard/PublicCard.spec.d.ts.map +1 -0
  18. package/dist/calendar/PublicCard/PublicCard.spec.js +301 -0
  19. package/dist/calendar/ShowCard/ShowCard.spec.d.ts +2 -0
  20. package/dist/calendar/ShowCard/ShowCard.spec.d.ts.map +1 -0
  21. package/dist/calendar/ShowCard/ShowCard.spec.js +714 -0
  22. package/dist/calendar/ShowTimeCard/ShowTimeCard.spec.d.ts +2 -0
  23. package/dist/calendar/ShowTimeCard/ShowTimeCard.spec.d.ts.map +1 -0
  24. package/dist/calendar/ShowTimeCard/ShowTimeCard.spec.js +241 -0
  25. package/dist/components/Layout/Section.spec.d.ts +2 -0
  26. package/dist/components/Layout/Section.spec.d.ts.map +1 -0
  27. package/dist/components/Layout/Section.spec.js +149 -0
  28. package/dist/components/Layout/Sidebar.spec.d.ts +2 -0
  29. package/dist/components/Layout/Sidebar.spec.d.ts.map +1 -0
  30. package/dist/components/Layout/Sidebar.spec.js +186 -0
  31. package/dist/components/Layout/Stack.spec.js +3 -3
  32. package/dist/constants/formOptions.spec.js +9 -5
  33. package/dist/datetime/__tests__/format.test.js +1 -1
  34. package/dist/datetime/__tests__/parse.test.js +1 -1
  35. package/dist/datetime/__tests__/timezone.test.js +124 -2
  36. package/dist/datetime/parse.js +1 -1
  37. package/dist/forms/createFieldTracker.spec.d.ts +2 -0
  38. package/dist/forms/createFieldTracker.spec.d.ts.map +1 -0
  39. package/dist/forms/createFieldTracker.spec.js +343 -0
  40. package/dist/forms/createFormStore.spec.d.ts +2 -0
  41. package/dist/forms/createFormStore.spec.d.ts.map +1 -0
  42. package/dist/forms/createFormStore.spec.js +689 -0
  43. package/dist/forms/createFormStore.svelte.js +0 -1
  44. package/dist/index.d.ts +4 -112
  45. package/dist/index.js +4 -190
  46. package/dist/patterns/data/DataGrid.spec.d.ts +2 -0
  47. package/dist/patterns/data/DataGrid.spec.d.ts.map +1 -0
  48. package/dist/patterns/data/DataGrid.spec.js +159 -0
  49. package/dist/patterns/data/DataList.spec.d.ts +2 -0
  50. package/dist/patterns/data/DataList.spec.d.ts.map +1 -0
  51. package/dist/patterns/data/DataList.spec.js +158 -0
  52. package/dist/patterns/data/DataTable.spec.d.ts +2 -0
  53. package/dist/patterns/data/DataTable.spec.d.ts.map +1 -0
  54. package/dist/patterns/data/DataTable.spec.js +196 -0
  55. package/dist/patterns/forms/FormActions.spec.js +10 -3
  56. package/dist/patterns/forms/FormGrid.spec.d.ts +2 -0
  57. package/dist/patterns/forms/FormGrid.spec.d.ts.map +1 -0
  58. package/dist/patterns/forms/FormGrid.spec.js +125 -0
  59. package/dist/patterns/forms/FormSection.spec.d.ts +2 -0
  60. package/dist/patterns/forms/FormSection.spec.d.ts.map +1 -0
  61. package/dist/patterns/forms/FormSection.spec.js +153 -0
  62. package/dist/patterns/layout/Sidebar.spec.d.ts +2 -0
  63. package/dist/patterns/layout/Sidebar.spec.d.ts.map +1 -0
  64. package/dist/patterns/layout/Sidebar.spec.js +159 -0
  65. package/dist/patterns/navigation/BottomNav.svelte +4 -4
  66. package/dist/patterns/navigation/Header.spec.js +33 -24
  67. package/dist/patterns/page/PageHeader.spec.d.ts +2 -0
  68. package/dist/patterns/page/PageHeader.spec.d.ts.map +1 -0
  69. package/dist/patterns/page/PageHeader.spec.js +167 -0
  70. package/dist/patterns/page/PageLayout.spec.d.ts +2 -0
  71. package/dist/patterns/page/PageLayout.spec.d.ts.map +1 -0
  72. package/dist/patterns/page/PageLayout.spec.js +145 -0
  73. package/dist/patterns/page/PageLoader.spec.js +5 -2
  74. package/dist/patterns/page/SectionHeader.spec.d.ts +2 -0
  75. package/dist/patterns/page/SectionHeader.spec.d.ts.map +1 -0
  76. package/dist/patterns/page/SectionHeader.spec.js +197 -0
  77. package/dist/presets/badges.spec.d.ts +2 -0
  78. package/dist/presets/badges.spec.d.ts.map +1 -0
  79. package/dist/presets/badges.spec.js +172 -0
  80. package/dist/presets/buttons.spec.d.ts +2 -0
  81. package/dist/presets/buttons.spec.d.ts.map +1 -0
  82. package/dist/presets/buttons.spec.js +135 -0
  83. package/dist/primitives/Accordion/Accordion.spec.d.ts +2 -0
  84. package/dist/primitives/Accordion/Accordion.spec.d.ts.map +1 -0
  85. package/dist/primitives/Accordion/Accordion.spec.js +83 -0
  86. package/dist/primitives/Accordion/AccordionItem.spec.d.ts +2 -0
  87. package/dist/primitives/Accordion/AccordionItem.spec.d.ts.map +1 -0
  88. package/dist/primitives/Accordion/AccordionItem.spec.js +661 -0
  89. package/dist/primitives/Accordion/AccordionItemWrapper.test.svelte +107 -0
  90. package/dist/primitives/Accordion/AccordionItemWrapper.test.svelte.d.ts +35 -0
  91. package/dist/primitives/Accordion/AccordionItemWrapper.test.svelte.d.ts.map +1 -0
  92. package/dist/primitives/Alert/Alert.spec.js +5 -2
  93. package/dist/primitives/Avatar/Avatar.spec.d.ts +2 -0
  94. package/dist/primitives/Avatar/Avatar.spec.d.ts.map +1 -0
  95. package/dist/primitives/Avatar/Avatar.spec.js +211 -0
  96. package/dist/primitives/Badges/Badge.spec.js +109 -68
  97. package/dist/primitives/BottomSheet/BottomSheet.spec.js +36 -27
  98. package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte +13 -0
  99. package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte.d.ts +7 -0
  100. package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte.d.ts.map +1 -0
  101. package/dist/primitives/Breadcrumb/Breadcrumb.spec.js +15 -13
  102. package/dist/primitives/Breadcrumb/Breadcrumb.svelte +5 -5
  103. package/dist/primitives/Button/Button.spec.js +83 -71
  104. package/dist/primitives/Button/ButtonSaveDemo.spec.js +100 -2
  105. package/dist/primitives/Button/ButtonVariantShowcase.spec.d.ts +2 -0
  106. package/dist/primitives/Button/ButtonVariantShowcase.spec.d.ts.map +1 -0
  107. package/dist/primitives/Button/ButtonVariantShowcase.spec.js +202 -0
  108. package/dist/primitives/Card.spec.js +1 -1
  109. package/dist/primitives/Checkbox/Checkbox.spec.d.ts +2 -0
  110. package/dist/primitives/Checkbox/Checkbox.spec.d.ts.map +1 -0
  111. package/dist/primitives/Checkbox/Checkbox.spec.js +252 -0
  112. package/dist/primitives/DarkModeToggle.spec.js +84 -51
  113. package/dist/primitives/Drawer/Drawer.spec.d.ts +2 -0
  114. package/dist/primitives/Drawer/Drawer.spec.d.ts.map +1 -0
  115. package/dist/primitives/Drawer/Drawer.spec.js +212 -0
  116. package/dist/primitives/Dropdown/Dropdown.spec.d.ts +2 -0
  117. package/dist/primitives/Dropdown/Dropdown.spec.d.ts.map +1 -0
  118. package/dist/primitives/Dropdown/Dropdown.spec.js +366 -0
  119. package/dist/primitives/Dropdown/DropdownItem.spec.d.ts +2 -0
  120. package/dist/primitives/Dropdown/DropdownItem.spec.d.ts.map +1 -0
  121. package/dist/primitives/Dropdown/DropdownItem.spec.js +182 -0
  122. package/dist/primitives/Icons/iconTestUtils.spec.d.ts +2 -0
  123. package/dist/primitives/Icons/iconTestUtils.spec.d.ts.map +1 -0
  124. package/dist/primitives/Icons/iconTestUtils.spec.js +235 -0
  125. package/dist/primitives/Input/Input.spec.js +14 -14
  126. package/dist/primitives/Input/Input.svelte +1 -14
  127. package/dist/primitives/Input/Input.svelte.d.ts.map +1 -1
  128. package/dist/primitives/Input/Select.spec.js +11 -17
  129. package/dist/primitives/Input/Textarea.spec.d.ts +2 -0
  130. package/dist/primitives/Input/Textarea.spec.d.ts.map +1 -0
  131. package/dist/primitives/Input/Textarea.spec.js +255 -0
  132. package/dist/primitives/Label/Label.spec.d.ts +2 -0
  133. package/dist/primitives/Label/Label.spec.d.ts.map +1 -0
  134. package/dist/primitives/Label/Label.spec.js +157 -0
  135. package/dist/primitives/Modal/Modal.spec.js +29 -25
  136. package/dist/primitives/Modal/ModalTestWrapper.svelte +65 -0
  137. package/dist/primitives/Modal/ModalTestWrapper.svelte.d.ts +23 -0
  138. package/dist/primitives/Modal/ModalTestWrapper.svelte.d.ts.map +1 -0
  139. package/dist/primitives/NumberInput/NumberInput.spec.d.ts +2 -0
  140. package/dist/primitives/NumberInput/NumberInput.spec.d.ts.map +1 -0
  141. package/dist/primitives/NumberInput/NumberInput.spec.js +235 -0
  142. package/dist/primitives/Pagination/Pagination.spec.d.ts +2 -0
  143. package/dist/primitives/Pagination/Pagination.spec.d.ts.map +1 -0
  144. package/dist/primitives/Pagination/Pagination.spec.js +266 -0
  145. package/dist/primitives/Radio/Radio.spec.d.ts +2 -0
  146. package/dist/primitives/Radio/Radio.spec.d.ts.map +1 -0
  147. package/dist/primitives/Radio/Radio.spec.js +206 -0
  148. package/dist/primitives/Skeleton/CardPlaceholder.spec.d.ts +2 -0
  149. package/dist/primitives/Skeleton/CardPlaceholder.spec.d.ts.map +1 -0
  150. package/dist/primitives/Skeleton/CardPlaceholder.spec.js +156 -0
  151. package/dist/primitives/Skeleton/ImagePlaceholder.spec.d.ts +2 -0
  152. package/dist/primitives/Skeleton/ImagePlaceholder.spec.d.ts.map +1 -0
  153. package/dist/primitives/Skeleton/ImagePlaceholder.spec.js +120 -0
  154. package/dist/primitives/Skeleton/ListPlaceholder.spec.d.ts +2 -0
  155. package/dist/primitives/Skeleton/ListPlaceholder.spec.d.ts.map +1 -0
  156. package/dist/primitives/Skeleton/ListPlaceholder.spec.js +220 -0
  157. package/dist/primitives/Skeleton/Skeleton.spec.d.ts +2 -0
  158. package/dist/primitives/Skeleton/Skeleton.spec.d.ts.map +1 -0
  159. package/dist/primitives/Skeleton/Skeleton.spec.js +173 -0
  160. package/dist/primitives/Spinner/Spinner.spec.js +25 -29
  161. package/dist/primitives/Tabs/TabItem.spec.d.ts +2 -0
  162. package/dist/primitives/Tabs/TabItem.spec.d.ts.map +1 -0
  163. package/dist/primitives/Tabs/TabItem.spec.js +130 -0
  164. package/dist/primitives/Tabs/Tabs.spec.d.ts +2 -0
  165. package/dist/primitives/Tabs/Tabs.spec.d.ts.map +1 -0
  166. package/dist/primitives/Tabs/Tabs.spec.js +295 -0
  167. package/dist/primitives/Tabs/TabsWithItems.test.svelte +18 -0
  168. package/dist/primitives/Tabs/TabsWithItems.test.svelte.d.ts +16 -0
  169. package/dist/primitives/Tabs/TabsWithItems.test.svelte.d.ts.map +1 -0
  170. package/dist/primitives/Toggle.spec.js +93 -77
  171. package/dist/primitives/Typography/Typography.spec.d.ts +2 -0
  172. package/dist/primitives/Typography/Typography.spec.d.ts.map +1 -0
  173. package/dist/primitives/Typography/Typography.spec.js +183 -0
  174. package/dist/primitives/ValidationError.spec.js +1 -1
  175. package/dist/primitives/index.d.ts +1 -0
  176. package/dist/primitives/index.js +3 -0
  177. package/dist/recipes/CropImage/CropImage.spec.js +1 -9
  178. package/dist/recipes/ImageUploader/ImageUploader.spec.d.ts +2 -0
  179. package/dist/recipes/ImageUploader/ImageUploader.spec.d.ts.map +1 -0
  180. package/dist/recipes/ImageUploader/ImageUploader.spec.js +1351 -0
  181. package/dist/recipes/SuperLogin/SuperLogin.spec.d.ts +2 -0
  182. package/dist/recipes/SuperLogin/SuperLogin.spec.d.ts.map +1 -0
  183. package/dist/recipes/SuperLogin/SuperLogin.spec.js +1436 -0
  184. package/dist/recipes/feedback/EmptyState/EmptyState.spec.d.ts +2 -0
  185. package/dist/recipes/feedback/EmptyState/EmptyState.spec.d.ts.map +1 -0
  186. package/dist/recipes/feedback/EmptyState/EmptyState.spec.js +202 -0
  187. package/dist/recipes/feedback/ErrorDisplay.spec.js +6 -6
  188. package/dist/recipes/feedback/StatusIndicator/StatusIndicator.spec.js +21 -17
  189. package/dist/recipes/fields/CheckboxField.spec.d.ts +2 -0
  190. package/dist/recipes/fields/CheckboxField.spec.d.ts.map +1 -0
  191. package/dist/recipes/fields/CheckboxField.spec.js +135 -0
  192. package/dist/recipes/fields/FormField.spec.d.ts +2 -0
  193. package/dist/recipes/fields/FormField.spec.d.ts.map +1 -0
  194. package/dist/recipes/fields/FormField.spec.js +159 -0
  195. package/dist/recipes/fields/RadioGroup.spec.d.ts +2 -0
  196. package/dist/recipes/fields/RadioGroup.spec.d.ts.map +1 -0
  197. package/dist/recipes/fields/RadioGroup.spec.js +199 -0
  198. package/dist/recipes/fields/SelectField.spec.d.ts +2 -0
  199. package/dist/recipes/fields/SelectField.spec.d.ts.map +1 -0
  200. package/dist/recipes/fields/SelectField.spec.js +188 -0
  201. package/dist/recipes/fields/TextareaField.spec.d.ts +2 -0
  202. package/dist/recipes/fields/TextareaField.spec.d.ts.map +1 -0
  203. package/dist/recipes/fields/TextareaField.spec.js +205 -0
  204. package/dist/recipes/fields/ToggleField.spec.d.ts +2 -0
  205. package/dist/recipes/fields/ToggleField.spec.d.ts.map +1 -0
  206. package/dist/recipes/fields/ToggleField.spec.js +153 -0
  207. package/dist/recipes/inputs/MultiSelect.spec.js +4 -3
  208. package/dist/recipes/inputs/MultiSelect.svelte +10 -3
  209. package/dist/recipes/inputs/MultiSelect.svelte.d.ts +2 -0
  210. package/dist/recipes/inputs/MultiSelect.svelte.d.ts.map +1 -1
  211. package/dist/recipes/inputs/OTPInput.spec.js +52 -39
  212. package/dist/recipes/inputs/PasswordInput.spec.d.ts +2 -0
  213. package/dist/recipes/inputs/PasswordInput.spec.d.ts.map +1 -0
  214. package/dist/recipes/inputs/PasswordInput.spec.js +410 -0
  215. package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.spec.js +253 -173
  216. package/dist/recipes/inputs/PasswordStrengthIndicator/TestWrapper.svelte +71 -0
  217. package/dist/recipes/inputs/PasswordStrengthIndicator/TestWrapper.svelte.d.ts +9 -0
  218. package/dist/recipes/inputs/PasswordStrengthIndicator/TestWrapper.svelte.d.ts.map +1 -0
  219. package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.spec.js +1246 -300
  220. package/dist/recipes/inputs/Search.spec.d.ts +2 -0
  221. package/dist/recipes/inputs/Search.spec.d.ts.map +1 -0
  222. package/dist/recipes/inputs/Search.spec.js +177 -0
  223. package/dist/recipes/inputs/SelectDropdown.spec.d.ts +2 -0
  224. package/dist/recipes/inputs/SelectDropdown.spec.d.ts.map +1 -0
  225. package/dist/recipes/inputs/SelectDropdown.spec.js +512 -0
  226. package/dist/recipes/modals/AlertModal.spec.d.ts +2 -0
  227. package/dist/recipes/modals/AlertModal.spec.d.ts.map +1 -0
  228. package/dist/recipes/modals/AlertModal.spec.js +432 -0
  229. package/dist/recipes/modals/ConfirmationModal.spec.js +36 -21
  230. package/dist/recipes/modals/InputModal.spec.d.ts +2 -0
  231. package/dist/recipes/modals/InputModal.spec.d.ts.map +1 -0
  232. package/dist/recipes/modals/InputModal.spec.js +872 -0
  233. package/dist/recipes/modals/ModalTestWrapper.spec.d.ts +2 -0
  234. package/dist/recipes/modals/ModalTestWrapper.spec.d.ts.map +1 -0
  235. package/dist/recipes/modals/ModalTestWrapper.spec.js +502 -0
  236. package/dist/recipes/modals/StatusModal.spec.d.ts +2 -0
  237. package/dist/recipes/modals/StatusModal.spec.d.ts.map +1 -0
  238. package/dist/recipes/modals/StatusModal.spec.js +599 -0
  239. package/dist/services/ShowService.spec.js +18 -15
  240. package/dist/stories/ButtonAuditDashboard.spec.d.ts +2 -0
  241. package/dist/stories/ButtonAuditDashboard.spec.d.ts.map +1 -0
  242. package/dist/stories/ButtonAuditDashboard.spec.js +913 -0
  243. package/dist/stories/ButtonAuditReview.spec.d.ts +2 -0
  244. package/dist/stories/ButtonAuditReview.spec.d.ts.map +1 -0
  245. package/dist/stories/ButtonAuditReview.spec.js +422 -0
  246. package/dist/stories/ButtonGridView.spec.d.ts +2 -0
  247. package/dist/stories/ButtonGridView.spec.d.ts.map +1 -0
  248. package/dist/stories/ButtonGridView.spec.js +667 -0
  249. package/dist/stories/ButtonShowcase.spec.d.ts +2 -0
  250. package/dist/stories/ButtonShowcase.spec.d.ts.map +1 -0
  251. package/dist/stories/ButtonShowcase.spec.js +499 -0
  252. package/dist/stories/PatternsGallery.spec.d.ts +2 -0
  253. package/dist/stories/PatternsGallery.spec.d.ts.map +1 -0
  254. package/dist/stories/PatternsGallery.spec.js +514 -0
  255. package/dist/stories/PrimitivesGallery.spec.d.ts +2 -0
  256. package/dist/stories/PrimitivesGallery.spec.d.ts.map +1 -0
  257. package/dist/stories/PrimitivesGallery.spec.js +813 -0
  258. package/dist/stories/RecipesGallery.spec.d.ts +2 -0
  259. package/dist/stories/RecipesGallery.spec.d.ts.map +1 -0
  260. package/dist/stories/RecipesGallery.spec.js +299 -0
  261. package/dist/stripe/useStripeTheme.spec.d.ts +2 -0
  262. package/dist/stripe/useStripeTheme.spec.d.ts.map +1 -0
  263. package/dist/stripe/useStripeTheme.spec.js +793 -0
  264. package/dist/telemetry.d.ts.map +1 -1
  265. package/dist/telemetry.js +6 -5
  266. package/dist/telemetry.spec.js +495 -12
  267. package/dist/tokens/__tests__/colors.test.d.ts +2 -0
  268. package/dist/tokens/__tests__/colors.test.d.ts.map +1 -0
  269. package/dist/tokens/__tests__/colors.test.js +152 -0
  270. package/dist/tokens/__tests__/radius.test.d.ts +2 -0
  271. package/dist/tokens/__tests__/radius.test.d.ts.map +1 -0
  272. package/dist/tokens/__tests__/radius.test.js +118 -0
  273. package/dist/tokens/__tests__/shadows.test.d.ts +2 -0
  274. package/dist/tokens/__tests__/shadows.test.d.ts.map +1 -0
  275. package/dist/tokens/__tests__/shadows.test.js +105 -0
  276. package/dist/tokens/__tests__/spacing.test.js +11 -8
  277. package/dist/tokens/__tests__/typography.test.d.ts +2 -0
  278. package/dist/tokens/__tests__/typography.test.d.ts.map +1 -0
  279. package/dist/tokens/__tests__/typography.test.js +156 -0
  280. package/dist/tokens/__tests__/z-index.test.d.ts +2 -0
  281. package/dist/tokens/__tests__/z-index.test.d.ts.map +1 -0
  282. package/dist/tokens/__tests__/z-index.test.js +121 -0
  283. package/dist/utils/apiConfig.spec.js +102 -1
  284. package/dist/utils/formatters.spec.d.ts +2 -0
  285. package/dist/utils/formatters.spec.d.ts.map +1 -0
  286. package/dist/utils/formatters.spec.js +82 -0
  287. package/dist/utils/transitions.spec.d.ts +2 -0
  288. package/dist/utils/transitions.spec.d.ts.map +1 -0
  289. package/dist/utils/transitions.spec.js +130 -0
  290. package/package.json +8 -3
@@ -0,0 +1,913 @@
1
+ import { render, screen } from '@testing-library/svelte';
2
+ import { expect, describe, it, beforeEach, vi } from 'vitest';
3
+ import userEvent from '@testing-library/user-event';
4
+ import ButtonAuditDashboard from './ButtonAuditDashboard.svelte';
5
+
6
+ // Mock the manifest
7
+ vi.mock('./button-audit-manifest.json', () => ({
8
+ default: {
9
+ generated: '2025-12-25T01:32:28.898Z',
10
+ totalButtons: 916,
11
+ categories: {
12
+ '🧩 Shared Components': [
13
+ {
14
+ route: '[component] AdminListMobileView',
15
+ file: 'components/AdminListMobileView/AdminListMobileView.svelte',
16
+ fullPath: '/Users/peet/repos/micdrop-frontend/src/components/AdminListMobileView/AdminListMobileView.svelte',
17
+ buttons: [
18
+ {
19
+ line: 101,
20
+ variant: 'blue-solid',
21
+ size: 'md',
22
+ loading: false,
23
+ disabled: false,
24
+ danger: false,
25
+ deemphasized: false,
26
+ text: 'Test Button 1'
27
+ },
28
+ {
29
+ line: 196,
30
+ variant: 'gray-outline',
31
+ size: 'sm',
32
+ loading: false,
33
+ disabled: true,
34
+ danger: false,
35
+ deemphasized: false,
36
+ text: 'Test Button 2'
37
+ },
38
+ {
39
+ line: 211,
40
+ variant: 'icon',
41
+ size: 'xs',
42
+ loading: true,
43
+ disabled: false,
44
+ danger: false,
45
+ deemphasized: false,
46
+ text: 'Icon Button'
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ route: '/admin/venues',
52
+ file: 'routes/admin/venues/+page.svelte',
53
+ fullPath: '/Users/peet/repos/micdrop-frontend/src/routes/admin/venues/+page.svelte',
54
+ buttons: [
55
+ {
56
+ line: 50,
57
+ variant: 'red-solid',
58
+ size: 'lg',
59
+ loading: false,
60
+ disabled: false,
61
+ danger: true,
62
+ deemphasized: false,
63
+ text: 'Delete'
64
+ }
65
+ ]
66
+ }
67
+ ],
68
+ '📊 Admin Routes': [
69
+ {
70
+ route: '/admin/users',
71
+ file: 'routes/admin/users/+page.svelte',
72
+ fullPath: '/Users/peet/repos/micdrop-frontend/src/routes/admin/users/+page.svelte',
73
+ buttons: [
74
+ {
75
+ line: 30,
76
+ variant: 'blue-outline',
77
+ size: 'md',
78
+ loading: false,
79
+ disabled: false,
80
+ danger: false,
81
+ deemphasized: false,
82
+ text: 'Edit User'
83
+ },
84
+ {
85
+ line: 45,
86
+ variant: 'gray-text',
87
+ size: 'sm',
88
+ loading: false,
89
+ disabled: false,
90
+ danger: false,
91
+ deemphasized: true,
92
+ text: 'Cancel'
93
+ }
94
+ ]
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ }));
100
+
101
+ describe('ButtonAuditDashboard', () => {
102
+ let user;
103
+
104
+ beforeEach(() => {
105
+ user = userEvent.setup();
106
+ // Reset document classes before each test
107
+ document.documentElement.classList.remove('dark');
108
+ });
109
+
110
+ describe('Component Rendering', () => {
111
+ it('should render the main dashboard', () => {
112
+ render(ButtonAuditDashboard);
113
+ expect(screen.getByText('Button Audit Dashboard')).toBeInTheDocument();
114
+ });
115
+
116
+ it('should render the subtitle with button counts', () => {
117
+ render(ButtonAuditDashboard);
118
+ expect(screen.getByText(/6 of 6 buttons from micdrop-frontend/)).toBeInTheDocument();
119
+ });
120
+
121
+ it('should render the generated timestamp', () => {
122
+ render(ButtonAuditDashboard);
123
+ const dateString = new Date('2025-12-25T01:32:28.898Z').toLocaleString();
124
+ expect(screen.getByText(new RegExp(dateString))).toBeInTheDocument();
125
+ });
126
+
127
+ it('should have sticky header', () => {
128
+ const { container } = render(ButtonAuditDashboard);
129
+ const header = container.querySelector('.sticky.top-0');
130
+ expect(header).toBeInTheDocument();
131
+ });
132
+
133
+ it('should have proper background color', () => {
134
+ const { container } = render(ButtonAuditDashboard);
135
+ const mainContainer = container.querySelector('.min-h-screen');
136
+ expect(mainContainer).toHaveClass('bg-gray-50', 'dark:bg-gray-900');
137
+ });
138
+ });
139
+
140
+ describe('Header Controls', () => {
141
+ it('should render Expand All button', () => {
142
+ render(ButtonAuditDashboard);
143
+ expect(screen.getByText('Expand All')).toBeInTheDocument();
144
+ });
145
+
146
+ it('should render Collapse All button', () => {
147
+ render(ButtonAuditDashboard);
148
+ expect(screen.getByText('Collapse All')).toBeInTheDocument();
149
+ });
150
+
151
+ it('should render dark mode toggle button', () => {
152
+ render(ButtonAuditDashboard);
153
+ const darkModeButton = screen.getByText(/Dark/);
154
+ expect(darkModeButton).toBeInTheDocument();
155
+ });
156
+
157
+ it('should toggle dark mode when clicking dark mode button', async () => {
158
+ render(ButtonAuditDashboard);
159
+ const darkModeButton = screen.getByRole('button', { name: /Dark/ });
160
+
161
+ // Initially should not have dark class
162
+ expect(document.documentElement.classList.contains('dark')).toBe(false);
163
+
164
+ // Click to enable dark mode
165
+ await user.click(darkModeButton);
166
+ expect(document.documentElement.classList.contains('dark')).toBe(true);
167
+ expect(screen.getByText(/Light/)).toBeInTheDocument();
168
+
169
+ // Click again to disable dark mode
170
+ await user.click(screen.getByRole('button', { name: /Light/ }));
171
+ expect(document.documentElement.classList.contains('dark')).toBe(false);
172
+ });
173
+
174
+ it('should show dark mode emoji when toggled', async () => {
175
+ const { container } = render(ButtonAuditDashboard);
176
+ const darkModeButton = screen.getByRole('button', { name: /Dark/ });
177
+
178
+ expect(container.textContent).toContain('🌙');
179
+
180
+ await user.click(darkModeButton);
181
+ expect(container.textContent).toContain('☀️');
182
+ });
183
+ });
184
+
185
+ describe('Filter Section', () => {
186
+ it('should render search input', () => {
187
+ render(ButtonAuditDashboard);
188
+ const searchInput = screen.getByPlaceholderText('Search button text...');
189
+ expect(searchInput).toBeInTheDocument();
190
+ });
191
+
192
+ it('should render variant filter dropdown', () => {
193
+ render(ButtonAuditDashboard);
194
+ expect(screen.getByText('All Variants')).toBeInTheDocument();
195
+ });
196
+
197
+ it('should render size filter dropdown', () => {
198
+ render(ButtonAuditDashboard);
199
+ expect(screen.getByText('All Sizes')).toBeInTheDocument();
200
+ });
201
+
202
+ it('should populate variant filter with all unique variants', () => {
203
+ const { container } = render(ButtonAuditDashboard);
204
+ const variantSelect = container.querySelector('select[bind\\:value]');
205
+
206
+ // Should have options for all variants in mock data
207
+ expect(screen.getAllByText('blue-solid').length).toBeGreaterThan(0);
208
+ expect(screen.getAllByText('gray-outline').length).toBeGreaterThan(0);
209
+ expect(screen.getAllByText('icon').length).toBeGreaterThan(0);
210
+ expect(screen.getAllByText('red-solid').length).toBeGreaterThan(0);
211
+ });
212
+
213
+ it('should populate size filter with all unique sizes', () => {
214
+ render(ButtonAuditDashboard);
215
+
216
+ // Should have options for all sizes in mock data
217
+ expect(screen.getAllByText('xs').length).toBeGreaterThan(0);
218
+ expect(screen.getAllByText('sm').length).toBeGreaterThan(0);
219
+ expect(screen.getAllByText('md').length).toBeGreaterThan(0);
220
+ expect(screen.getAllByText('lg').length).toBeGreaterThan(0);
221
+ });
222
+
223
+ it('should filter buttons by search query', async () => {
224
+ render(ButtonAuditDashboard);
225
+ const searchInput = screen.getByPlaceholderText('Search button text...');
226
+
227
+ await user.type(searchInput, 'Delete');
228
+
229
+ // Should update the filtered count
230
+ expect(screen.getByText(/1 of 6 buttons/)).toBeInTheDocument();
231
+ });
232
+
233
+ it('should filter buttons by variant', async () => {
234
+ render(ButtonAuditDashboard);
235
+ const variantSelects = screen.getAllByRole('combobox');
236
+ const variantSelect = variantSelects[0]; // First select is variant filter
237
+
238
+ await user.selectOptions(variantSelect, 'blue-solid');
239
+
240
+ // Should filter to only blue-solid buttons (1 in mock data)
241
+ expect(screen.getByText(/1 of 6 buttons/)).toBeInTheDocument();
242
+ });
243
+
244
+ it('should filter buttons by size', async () => {
245
+ render(ButtonAuditDashboard);
246
+ const sizeSelects = screen.getAllByRole('combobox');
247
+ const sizeSelect = sizeSelects[1]; // Second select is size filter
248
+
249
+ await user.selectOptions(sizeSelect, 'md');
250
+
251
+ // Should filter to only md buttons (2 in mock data: blue-solid and blue-outline)
252
+ expect(screen.getByText(/2 of 6 buttons/)).toBeInTheDocument();
253
+ });
254
+ });
255
+
256
+ describe('Category Sections', () => {
257
+ it('should render all categories', () => {
258
+ render(ButtonAuditDashboard);
259
+ expect(screen.getByText('🧩 Shared Components')).toBeInTheDocument();
260
+ expect(screen.getByText('📊 Admin Routes')).toBeInTheDocument();
261
+ });
262
+
263
+ it('should display category button counts', () => {
264
+ render(ButtonAuditDashboard);
265
+
266
+ // Shared Components has 4 buttons
267
+ expect(screen.getByText('4 buttons')).toBeInTheDocument();
268
+ // Admin Routes has 2 buttons
269
+ expect(screen.getByText('2 buttons')).toBeInTheDocument();
270
+ });
271
+
272
+ it('should display file counts for each category', () => {
273
+ render(ButtonAuditDashboard);
274
+ expect(screen.getByText(/in 2 files/)).toBeInTheDocument();
275
+ expect(screen.getByText(/in 1 files/)).toBeInTheDocument();
276
+ });
277
+
278
+ it('should start with categories collapsed', () => {
279
+ const { container } = render(ButtonAuditDashboard);
280
+
281
+ // Look for collapsed indicator (▶)
282
+ expect(container.textContent).toContain('▶');
283
+ });
284
+
285
+ it('should expand category when clicked', async () => {
286
+ const { container } = render(ButtonAuditDashboard);
287
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
288
+
289
+ await user.click(categoryButton);
290
+
291
+ // Should show expanded indicator (▼)
292
+ expect(container.textContent).toContain('▼');
293
+
294
+ // Should show file sections
295
+ expect(screen.getByText(/components\/AdminListMobileView/)).toBeInTheDocument();
296
+ });
297
+
298
+ it('should collapse category when clicked again', async () => {
299
+ const { container } = render(ButtonAuditDashboard);
300
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
301
+
302
+ // Expand
303
+ await user.click(categoryButton);
304
+ expect(container.textContent).toContain('▼');
305
+
306
+ // Collapse
307
+ await user.click(categoryButton);
308
+ expect(container.textContent).toContain('▶');
309
+ });
310
+
311
+ it('should sort categories by button count', () => {
312
+ const { container } = render(ButtonAuditDashboard);
313
+ const categoryHeaders = Array.from(container.querySelectorAll('h2'));
314
+ const categoryNames = categoryHeaders.map(h => h.textContent);
315
+
316
+ // Shared Components (4 buttons) should come before Admin Routes (2 buttons)
317
+ const sharedIndex = categoryNames.findIndex(name => name.includes('Shared Components'));
318
+ const adminIndex = categoryNames.findIndex(name => name.includes('Admin Routes'));
319
+
320
+ expect(sharedIndex).toBeLessThan(adminIndex);
321
+ });
322
+ });
323
+
324
+ describe('File Sections', () => {
325
+ it('should render file paths when category is expanded', async () => {
326
+ render(ButtonAuditDashboard);
327
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
328
+
329
+ await user.click(categoryButton);
330
+
331
+ expect(screen.getByText(/AdminListMobileView\.svelte/)).toBeInTheDocument();
332
+ expect(screen.getByText(/admin\/venues\/\+page\.svelte/)).toBeInTheDocument();
333
+ });
334
+
335
+ it('should display button count for each file', async () => {
336
+ render(ButtonAuditDashboard);
337
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
338
+
339
+ await user.click(categoryButton);
340
+
341
+ expect(screen.getByText('3 buttons')).toBeInTheDocument();
342
+ expect(screen.getByText('1 buttons')).toBeInTheDocument();
343
+ });
344
+
345
+ it('should render VS Code open links', async () => {
346
+ render(ButtonAuditDashboard);
347
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
348
+
349
+ await user.click(categoryButton);
350
+
351
+ const openLinks = screen.getAllByText(/📂 Open/);
352
+ expect(openLinks.length).toBeGreaterThan(0);
353
+
354
+ // Check VS Code link format
355
+ expect(openLinks[0].closest('a')).toHaveAttribute('href', expect.stringContaining('vscode://file'));
356
+ });
357
+
358
+ it('should show preview button for route pages', async () => {
359
+ render(ButtonAuditDashboard);
360
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
361
+
362
+ await user.click(categoryButton);
363
+
364
+ // routes/admin/venues/+page.svelte should have preview
365
+ expect(screen.getByText('👁️ Preview')).toBeInTheDocument();
366
+ });
367
+
368
+ it('should not show preview button for components', async () => {
369
+ render(ButtonAuditDashboard);
370
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
371
+
372
+ await user.click(categoryButton);
373
+
374
+ // components/AdminListMobileView should not have preview
375
+ const previewButtons = screen.queryAllByText('👁️ Preview');
376
+ // Only routes should have preview, not components
377
+ expect(previewButtons.length).toBe(1);
378
+ });
379
+
380
+ it('should expand file section when clicked', async () => {
381
+ render(ButtonAuditDashboard);
382
+
383
+ // First expand category
384
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
385
+ await user.click(categoryButton);
386
+
387
+ // Then expand file
388
+ const fileButton = screen.getByRole('button', { name: /AdminListMobileView/ });
389
+ await user.click(fileButton);
390
+
391
+ // Should show button grid
392
+ expect(screen.getByText('Test Button 1')).toBeInTheDocument();
393
+ });
394
+ });
395
+
396
+ describe('Button Cards', () => {
397
+ beforeEach(async () => {
398
+ render(ButtonAuditDashboard);
399
+
400
+ // Expand category and file to show buttons
401
+ const categoryButtons = screen.getAllByRole('button', { name: /🧩 Shared Components/ });
402
+ await userEvent.setup().click(categoryButtons[0]);
403
+
404
+ // Find file button by text content
405
+ const fileCodeElement = screen.getByText(/AdminListMobileView\.svelte/);
406
+ const fileButton = fileCodeElement.closest('button');
407
+ if (fileButton) {
408
+ await userEvent.setup().click(fileButton);
409
+ }
410
+ });
411
+
412
+ it('should render button previews', () => {
413
+ // Should render actual Button components
414
+ const buttons = screen.getAllByRole('button');
415
+ expect(buttons.length).toBeGreaterThan(3); // More than just expand/collapse buttons
416
+ });
417
+
418
+ it('should display button text', () => {
419
+ expect(screen.getByText('Test Button 1')).toBeInTheDocument();
420
+ expect(screen.getByText('Test Button 2')).toBeInTheDocument();
421
+ expect(screen.getByText('Icon Button')).toBeInTheDocument();
422
+ });
423
+
424
+ it('should display variant badges', () => {
425
+ expect(screen.getAllByText('blue-solid').length).toBeGreaterThan(0);
426
+ expect(screen.getAllByText('gray-outline').length).toBeGreaterThan(0);
427
+ expect(screen.getAllByText('icon').length).toBeGreaterThan(0);
428
+ });
429
+
430
+ it('should display size badges', () => {
431
+ expect(screen.getAllByText('md').length).toBeGreaterThan(0);
432
+ expect(screen.getAllByText('sm').length).toBeGreaterThan(0);
433
+ expect(screen.getAllByText('xs').length).toBeGreaterThan(0);
434
+ });
435
+
436
+ it('should display loading badge when applicable', () => {
437
+ expect(screen.getByText('loading')).toBeInTheDocument();
438
+ });
439
+
440
+ it('should display disabled badge when applicable', () => {
441
+ expect(screen.getByText('disabled')).toBeInTheDocument();
442
+ });
443
+
444
+ it('should display danger badge when applicable', async () => {
445
+ // Need to expand a different file that has the danger button
446
+ const { container } = render(ButtonAuditDashboard);
447
+
448
+ const expandButtons = screen.getAllByRole('button', { name: 'Expand All' });
449
+ await userEvent.setup().click(expandButtons[0]);
450
+
451
+ // The danger badge should appear when a button has danger: true
452
+ expect(screen.getByText('danger')).toBeInTheDocument();
453
+ });
454
+
455
+ it('should display line numbers', () => {
456
+ expect(screen.getByText('Line 101')).toBeInTheDocument();
457
+ expect(screen.getByText('Line 196')).toBeInTheDocument();
458
+ expect(screen.getByText('Line 211')).toBeInTheDocument();
459
+ });
460
+
461
+ it('should render VS Code links for each button', () => {
462
+ const codeLinks = screen.getAllByText('Open in Code →');
463
+ expect(codeLinks.length).toBeGreaterThan(0);
464
+
465
+ // Check that link includes line number
466
+ expect(codeLinks[0].closest('a')).toHaveAttribute('href', expect.stringContaining(':101'));
467
+ });
468
+
469
+ it('should truncate long button text', () => {
470
+ // Truncation logic is in the component, verified it renders
471
+ const { container } = render(ButtonAuditDashboard);
472
+ expect(container).toBeInTheDocument();
473
+ });
474
+
475
+ it('should display button text in quotes below metadata', () => {
476
+ // Look for quoted text
477
+ expect(screen.getByText(/"Test Button 1"/)).toBeInTheDocument();
478
+ expect(screen.getByText(/"Test Button 2"/)).toBeInTheDocument();
479
+ });
480
+
481
+ it('should render buttons in a grid layout', () => {
482
+ // Grid layout is part of the button cards section, verified it renders
483
+ const { container } = render(ButtonAuditDashboard);
484
+ // Look for grid classes
485
+ const hasGrid = container.textContent.includes('Test Button');
486
+ expect(hasGrid || container.querySelector('[class*="grid"]')).toBeTruthy();
487
+ });
488
+ });
489
+
490
+ describe('Expand/Collapse All', () => {
491
+ it('should expand all categories and files when clicking Expand All', async () => {
492
+ render(ButtonAuditDashboard);
493
+ const expandAllButton = screen.getByRole('button', { name: 'Expand All' });
494
+
495
+ await user.click(expandAllButton);
496
+
497
+ // Should show all buttons
498
+ expect(screen.getByText('Test Button 1')).toBeInTheDocument();
499
+ expect(screen.getByText('Edit User')).toBeInTheDocument();
500
+ });
501
+
502
+ it('should collapse all categories when clicking Collapse All', async () => {
503
+ render(ButtonAuditDashboard);
504
+
505
+ // First expand all
506
+ const expandAllButton = screen.getByRole('button', { name: 'Expand All' });
507
+ await user.click(expandAllButton);
508
+
509
+ // Then collapse all
510
+ const collapseAllButton = screen.getByRole('button', { name: 'Collapse All' });
511
+ await user.click(collapseAllButton);
512
+
513
+ // Buttons should not be visible
514
+ expect(screen.queryByText('Test Button 1')).not.toBeInTheDocument();
515
+ });
516
+ });
517
+
518
+ describe('Preview Modal', () => {
519
+ it('should not show preview modal by default', () => {
520
+ const { container } = render(ButtonAuditDashboard);
521
+ const modal = container.querySelector('.fixed.inset-0.z-\\[100\\]');
522
+ expect(modal).not.toBeInTheDocument();
523
+ });
524
+
525
+ it('should open preview modal when clicking preview button', async () => {
526
+ const { container } = render(ButtonAuditDashboard);
527
+
528
+ // Expand to show preview button
529
+ const categoryButtons = screen.getAllByRole('button', { name: /🧩 Shared Components/ });
530
+ await user.click(categoryButtons[0]);
531
+
532
+ const previewButton = screen.getByText('👁️ Preview');
533
+ await user.click(previewButton);
534
+
535
+ // Modal should appear - check for iframe which is the key part of the preview
536
+ const iframe = container.querySelector('iframe');
537
+ expect(iframe).toBeInTheDocument();
538
+ expect(iframe).toHaveAttribute('title', 'Page preview');
539
+ });
540
+
541
+ it('should display correct URL in preview modal', async () => {
542
+ render(ButtonAuditDashboard);
543
+
544
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
545
+ await user.click(categoryButton);
546
+
547
+ const previewButton = screen.getByText('👁️ Preview');
548
+ await user.click(previewButton);
549
+
550
+ // Should show the route
551
+ expect(screen.getByText('/admin/venues')).toBeInTheDocument();
552
+ });
553
+
554
+ it('should display file path in preview modal header', async () => {
555
+ render(ButtonAuditDashboard);
556
+
557
+ const categoryButtons = screen.getAllByRole('button', { name: /🧩 Shared Components/ });
558
+ await user.click(categoryButtons[0]);
559
+
560
+ const previewButton = screen.getByText('👁️ Preview');
561
+ await user.click(previewButton);
562
+
563
+ expect(screen.getAllByText(/routes\/admin\/venues\/\+page\.svelte/).length).toBeGreaterThan(0);
564
+ });
565
+
566
+ it('should render iframe with correct URL', async () => {
567
+ const { container } = render(ButtonAuditDashboard);
568
+
569
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
570
+ await user.click(categoryButton);
571
+
572
+ const previewButton = screen.getByText('👁️ Preview');
573
+ await user.click(previewButton);
574
+
575
+ const iframe = container.querySelector('iframe');
576
+ expect(iframe).toHaveAttribute('src', 'http://localhost:5173/admin/venues');
577
+ });
578
+
579
+ it('should show "Open in new tab" link', async () => {
580
+ render(ButtonAuditDashboard);
581
+
582
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
583
+ await user.click(categoryButton);
584
+
585
+ const previewButton = screen.getByText('👁️ Preview');
586
+ await user.click(previewButton);
587
+
588
+ const newTabLink = screen.getByText('Open in new tab ↗');
589
+ expect(newTabLink).toHaveAttribute('href', 'http://localhost:5173/admin/venues');
590
+ expect(newTabLink).toHaveAttribute('target', '_blank');
591
+ });
592
+
593
+ it('should close modal when clicking close button', async () => {
594
+ const { container } = render(ButtonAuditDashboard);
595
+
596
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
597
+ await user.click(categoryButton);
598
+
599
+ const previewButton = screen.getByText('👁️ Preview');
600
+ await user.click(previewButton);
601
+
602
+ const closeButton = screen.getByRole('button', { name: '✕' });
603
+ await user.click(closeButton);
604
+
605
+ // Modal should be gone
606
+ const modal = container.querySelector('.fixed.inset-0.z-\\[100\\]');
607
+ expect(modal).not.toBeInTheDocument();
608
+ });
609
+
610
+ it('should show dev server warning in modal footer', async () => {
611
+ render(ButtonAuditDashboard);
612
+
613
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
614
+ await user.click(categoryButton);
615
+
616
+ const previewButton = screen.getByText('👁️ Preview');
617
+ await user.click(previewButton);
618
+
619
+ expect(screen.getByText(/Preview requires micdrop-frontend dev server/)).toBeInTheDocument();
620
+ expect(screen.getByText(/http:\/\/localhost:5173/)).toBeInTheDocument();
621
+ });
622
+
623
+ it('should handle keyboard interaction on preview button', async () => {
624
+ render(ButtonAuditDashboard);
625
+
626
+ const categoryButtons = screen.getAllByRole('button', { name: /🧩 Shared Components/ });
627
+ await user.click(categoryButtons[0]);
628
+
629
+ const previewButton = screen.getByText('👁️ Preview');
630
+
631
+ // Check that preview button has tabindex for keyboard navigation
632
+ expect(previewButton.getAttribute('tabindex')).toBe('0');
633
+ expect(previewButton.getAttribute('role')).toBe('button');
634
+ });
635
+ });
636
+
637
+ describe('Variant Distribution Footer', () => {
638
+ it('should render variant distribution section', () => {
639
+ render(ButtonAuditDashboard);
640
+ expect(screen.getByText('Variant Distribution')).toBeInTheDocument();
641
+ });
642
+
643
+ it('should display all unique variants with counts', () => {
644
+ render(ButtonAuditDashboard);
645
+
646
+ // Check that variants are listed with their counts (use getAllByText since they appear in multiple places)
647
+ expect(screen.getAllByText('blue-solid').length).toBeGreaterThan(0);
648
+ expect(screen.getAllByText('gray-outline').length).toBeGreaterThan(0);
649
+ expect(screen.getAllByText('icon').length).toBeGreaterThan(0);
650
+ expect(screen.getAllByText('red-solid').length).toBeGreaterThan(0);
651
+ expect(screen.getAllByText('blue-outline').length).toBeGreaterThan(0);
652
+ });
653
+
654
+ it('should use correct variant colors', () => {
655
+ const { container } = render(ButtonAuditDashboard);
656
+
657
+ // Check for specific color classes
658
+ expect(container.querySelector('.bg-blue-100.text-blue-800')).toBeInTheDocument();
659
+ expect(container.querySelector('.bg-gray-100.text-gray-800')).toBeInTheDocument();
660
+ });
661
+
662
+ it('should render in grid layout', () => {
663
+ const { container } = render(ButtonAuditDashboard);
664
+ const grid = container.querySelector('.grid.grid-cols-2.md\\:grid-cols-4.lg\\:grid-cols-6');
665
+ expect(grid).toBeInTheDocument();
666
+ });
667
+ });
668
+
669
+ describe('Helper Functions', () => {
670
+ it('should identify previewable files correctly', async () => {
671
+ render(ButtonAuditDashboard);
672
+
673
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
674
+ await user.click(categoryButton);
675
+
676
+ // routes/admin/venues/+page.svelte should be previewable
677
+ expect(screen.getByText('👁️ Preview')).toBeInTheDocument();
678
+
679
+ // components should not be previewable
680
+ const previewButtons = screen.queryAllByText('👁️ Preview');
681
+ expect(previewButtons.length).toBe(1);
682
+ });
683
+
684
+ it('should generate correct VS Code links', async () => {
685
+ render(ButtonAuditDashboard);
686
+
687
+ const categoryButton = screen.getByRole('button', { name: /🧩 Shared Components/ });
688
+ await user.click(categoryButton);
689
+
690
+ const openLink = screen.getAllByText('📂 Open')[0];
691
+ const href = openLink.closest('a')?.getAttribute('href');
692
+
693
+ expect(href).toContain('vscode://file');
694
+ expect(href).toContain('/Users/peet/repos/micdrop-frontend');
695
+ });
696
+
697
+ it('should return correct variant colors', () => {
698
+ const { container } = render(ButtonAuditDashboard);
699
+
700
+ // Check that variant distribution section has color classes
701
+ expect(container.querySelector('.bg-blue-100')).toBeInTheDocument();
702
+ expect(container.querySelector('.bg-red-100')).toBeInTheDocument();
703
+ expect(container.querySelector('.bg-purple-100')).toBeInTheDocument();
704
+ });
705
+ });
706
+
707
+ describe('Layout and Responsiveness', () => {
708
+ it('should have max-width container', () => {
709
+ const { container } = render(ButtonAuditDashboard);
710
+ const mainContainer = container.querySelector('.max-w-7xl');
711
+ expect(mainContainer).toBeInTheDocument();
712
+ });
713
+
714
+ it('should have proper spacing', () => {
715
+ const { container } = render(ButtonAuditDashboard);
716
+ expect(container.querySelector('.space-y-4')).toBeInTheDocument();
717
+ });
718
+
719
+ it('should render responsive grid classes', () => {
720
+ const { container } = render(ButtonAuditDashboard);
721
+ expect(container.textContent).toBeTruthy();
722
+
723
+ // Check for responsive classes in the DOM
724
+ const responsiveElements = container.querySelectorAll('[class*="md:"], [class*="lg:"]');
725
+ expect(responsiveElements.length).toBeGreaterThan(0);
726
+ });
727
+
728
+ it('should have proper border and shadow styling', () => {
729
+ const { container } = render(ButtonAuditDashboard);
730
+ const header = container.querySelector('.border-b.shadow-sm');
731
+ expect(header).toBeInTheDocument();
732
+ });
733
+ });
734
+
735
+ describe('Filter Combinations', () => {
736
+ it('should combine variant and size filters', async () => {
737
+ render(ButtonAuditDashboard);
738
+
739
+ const selects = screen.getAllByRole('combobox');
740
+ const variantSelect = selects[0];
741
+ const sizeSelect = selects[1];
742
+
743
+ await user.selectOptions(variantSelect, 'gray-outline');
744
+ await user.selectOptions(sizeSelect, 'sm');
745
+
746
+ // Only 1 button matches both filters
747
+ expect(screen.getByText(/1 of 6 buttons/)).toBeInTheDocument();
748
+ });
749
+
750
+ it('should combine search with variant filter', async () => {
751
+ render(ButtonAuditDashboard);
752
+
753
+ const searchInput = screen.getByPlaceholderText('Search button text...');
754
+ const variantSelect = screen.getAllByRole('combobox')[0];
755
+
756
+ await user.type(searchInput, 'Test');
757
+ await user.selectOptions(variantSelect, 'blue-solid');
758
+
759
+ // Should find buttons matching both criteria
760
+ expect(screen.getByText(/1 of 6 buttons/)).toBeInTheDocument();
761
+ });
762
+
763
+ it('should show 0 results when no buttons match filters', async () => {
764
+ render(ButtonAuditDashboard);
765
+
766
+ const searchInput = screen.getByPlaceholderText('Search button text...');
767
+ await user.type(searchInput, 'NonexistentButton');
768
+
769
+ expect(screen.getByText(/0 of 6 buttons/)).toBeInTheDocument();
770
+ });
771
+ });
772
+
773
+ describe('Dark Mode Support', () => {
774
+ it('should have dark mode classes on elements', () => {
775
+ const { container } = render(ButtonAuditDashboard);
776
+
777
+ // Check for dark: prefixed classes
778
+ const darkModeElements = container.querySelectorAll('[class*="dark:"]');
779
+ expect(darkModeElements.length).toBeGreaterThan(0);
780
+ });
781
+
782
+ it('should toggle dark classes on html element', async () => {
783
+ render(ButtonAuditDashboard);
784
+ const darkModeButton = screen.getByRole('button', { name: /Dark/ });
785
+
786
+ await user.click(darkModeButton);
787
+ expect(document.documentElement.classList.contains('dark')).toBe(true);
788
+
789
+ await user.click(screen.getByRole('button', { name: /Light/ }));
790
+ expect(document.documentElement.classList.contains('dark')).toBe(false);
791
+ });
792
+
793
+ it('should style dark mode button differently when active', async () => {
794
+ render(ButtonAuditDashboard);
795
+ const darkModeButton = screen.getByRole('button', { name: /Dark/ });
796
+
797
+ expect(darkModeButton).toHaveClass('bg-gray-800');
798
+
799
+ await user.click(darkModeButton);
800
+ const lightModeButton = screen.getByRole('button', { name: /Light/ });
801
+ expect(lightModeButton).toHaveClass('bg-yellow-500');
802
+ });
803
+ });
804
+
805
+ describe('Accessibility', () => {
806
+ it('should use semantic HTML', () => {
807
+ const { container } = render(ButtonAuditDashboard);
808
+ expect(container.querySelector('h1')).toBeInTheDocument();
809
+ expect(container.querySelector('h2')).toBeInTheDocument();
810
+ });
811
+
812
+ it('should have accessible button labels', () => {
813
+ render(ButtonAuditDashboard);
814
+ expect(screen.getByRole('button', { name: /Expand All/ })).toBeInTheDocument();
815
+ expect(screen.getByRole('button', { name: /Collapse All/ })).toBeInTheDocument();
816
+ });
817
+
818
+ it('should have accessible form controls', () => {
819
+ render(ButtonAuditDashboard);
820
+ expect(screen.getByPlaceholderText('Search button text...')).toBeInTheDocument();
821
+ expect(screen.getAllByRole('combobox').length).toBe(2);
822
+ });
823
+
824
+ it('should support keyboard navigation on preview buttons', async () => {
825
+ render(ButtonAuditDashboard);
826
+
827
+ const categoryButtons = screen.getAllByRole('button', { name: /🧩 Shared Components/ });
828
+ await user.click(categoryButtons[0]);
829
+
830
+ const previewButton = screen.getByText('👁️ Preview');
831
+ expect(previewButton.getAttribute('tabindex')).toBe('0');
832
+ });
833
+ });
834
+
835
+ describe('Data Integrity', () => {
836
+ it('should display correct total button count', () => {
837
+ render(ButtonAuditDashboard);
838
+ expect(screen.getByText(/6 of 6 buttons/)).toBeInTheDocument();
839
+ });
840
+
841
+ it('should match button count with category totals', () => {
842
+ render(ButtonAuditDashboard);
843
+
844
+ // 4 + 2 = 6 total
845
+ expect(screen.getByText('4 buttons')).toBeInTheDocument();
846
+ expect(screen.getByText('2 buttons')).toBeInTheDocument();
847
+ });
848
+
849
+ it('should update filtered count when filters change', async () => {
850
+ render(ButtonAuditDashboard);
851
+
852
+ const searchInput = screen.getByPlaceholderText('Search button text...');
853
+
854
+ // Initial state
855
+ expect(screen.getByText(/6 of 6 buttons/)).toBeInTheDocument();
856
+
857
+ // After filtering for "Delete" (1 button matches)
858
+ await user.type(searchInput, 'Delete');
859
+ expect(screen.getByText(/1 of 6 buttons/)).toBeInTheDocument();
860
+ });
861
+
862
+ it('should preserve total count while filtering', async () => {
863
+ render(ButtonAuditDashboard);
864
+
865
+ const searchInput = screen.getByPlaceholderText('Search button text...');
866
+ await user.type(searchInput, 'xyz');
867
+
868
+ // Should show 0 of 6, not 0 of 0
869
+ expect(screen.getByText(/0 of 6 buttons/)).toBeInTheDocument();
870
+ });
871
+ });
872
+
873
+ describe('Edge Cases', () => {
874
+ it('should handle empty button text gracefully', async () => {
875
+ // Mock includes button with "(no text)"
876
+ render(ButtonAuditDashboard);
877
+
878
+ const expandAll = screen.getByRole('button', { name: 'Expand All' });
879
+ await user.click(expandAll);
880
+
881
+ // Should render "Button" as fallback for no text
882
+ const { container } = render(ButtonAuditDashboard);
883
+ expect(container.textContent).toBeTruthy();
884
+ });
885
+
886
+ it('should handle categories with no visible buttons after filtering', async () => {
887
+ render(ButtonAuditDashboard);
888
+
889
+ const searchInput = screen.getByPlaceholderText('Search button text...');
890
+ await user.type(searchInput, 'NonexistentText');
891
+
892
+ // Categories with 0 visible buttons should not be rendered
893
+ expect(screen.queryByText('🧩 Shared Components')).not.toBeInTheDocument();
894
+ });
895
+
896
+ it('should handle very long button text with truncation', () => {
897
+ const { container } = render(ButtonAuditDashboard);
898
+
899
+ // Check that ellipsis logic exists in rendered output
900
+ const expandAll = screen.getByRole('button', { name: 'Expand All' });
901
+ userEvent.setup().click(expandAll);
902
+
903
+ setTimeout(() => {
904
+ const buttons = container.querySelectorAll('button');
905
+ buttons.forEach(btn => {
906
+ if (btn.textContent && btn.textContent.length > 33) {
907
+ expect(btn.textContent).toContain('...');
908
+ }
909
+ });
910
+ }, 100);
911
+ });
912
+ });
913
+ });