microui-wc 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/AGENTS.md +71 -71
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +14 -9
  4. package/dist/AGENTS.md +71 -71
  5. package/dist/README.md +14 -9
  6. package/dist/microui.css +1 -1
  7. package/dist/microui.esm.js.map +1 -1
  8. package/dist/microui.min.js.map +1 -1
  9. package/docs/getting-started.md +3 -3
  10. package/package.json +39 -11
  11. package/src/components/mu-schema-form.js +1 -1
  12. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  13. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -33
  14. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  15. package/.github/workflows/ci.yml +0 -42
  16. package/.github/workflows/deploy-pages.yml +0 -112
  17. package/CODE_OF_CONDUCT.md +0 -59
  18. package/CONTRIBUTING.md +0 -156
  19. package/SECURITY.md +0 -58
  20. package/app/.generated/routes/alerts.js +0 -8
  21. package/app/.generated/routes/avatars.js +0 -8
  22. package/app/.generated/routes/badges.js +0 -8
  23. package/app/.generated/routes/buttons.js +0 -10
  24. package/app/.generated/routes/cards.js +0 -10
  25. package/app/.generated/routes/checkboxes.js +0 -9
  26. package/app/.generated/routes/chips.js +0 -8
  27. package/app/.generated/routes/dropdowns.js +0 -9
  28. package/app/.generated/routes/home.js +0 -7
  29. package/app/.generated/routes/icons.js +0 -9
  30. package/app/.generated/routes/inputs.js +0 -10
  31. package/app/.generated/routes/installation.js +0 -7
  32. package/app/.generated/routes/layout.js +0 -9
  33. package/app/.generated/routes/modals.js +0 -9
  34. package/app/.generated/routes/navbar.js +0 -7
  35. package/app/.generated/routes/progress.js +0 -9
  36. package/app/.generated/routes/radios.js +0 -9
  37. package/app/.generated/routes/switches.js +0 -9
  38. package/app/.generated/routes/tabs.js +0 -8
  39. package/app/.generated/routes/toasts.js +0 -9
  40. package/app/index.html +0 -67
  41. package/app/pages/alerts.html +0 -23
  42. package/app/pages/avatars.html +0 -22
  43. package/app/pages/badges.html +0 -22
  44. package/app/pages/buttons.html +0 -71
  45. package/app/pages/cards.html +0 -54
  46. package/app/pages/checkboxes.html +0 -39
  47. package/app/pages/chips.html +0 -23
  48. package/app/pages/dropdowns.html +0 -41
  49. package/app/pages/home.html +0 -59
  50. package/app/pages/icons.html +0 -29
  51. package/app/pages/inputs.html +0 -66
  52. package/app/pages/installation.html +0 -34
  53. package/app/pages/layout.html +0 -30
  54. package/app/pages/modals.html +0 -21
  55. package/app/pages/navbar.html +0 -22
  56. package/app/pages/progress.html +0 -35
  57. package/app/pages/radios.html +0 -40
  58. package/app/pages/switches.html +0 -39
  59. package/app/pages/tabs.html +0 -30
  60. package/app/pages/toasts.html +0 -22
  61. package/app-dist/index.html +0 -67
  62. package/app-dist/pages/alerts.html +0 -23
  63. package/app-dist/pages/avatars.html +0 -22
  64. package/app-dist/pages/badges.html +0 -22
  65. package/app-dist/pages/buttons.html +0 -71
  66. package/app-dist/pages/cards.html +0 -54
  67. package/app-dist/pages/checkboxes.html +0 -39
  68. package/app-dist/pages/chips.html +0 -23
  69. package/app-dist/pages/dropdowns.html +0 -41
  70. package/app-dist/pages/home.html +0 -59
  71. package/app-dist/pages/icons.html +0 -29
  72. package/app-dist/pages/inputs.html +0 -66
  73. package/app-dist/pages/installation.html +0 -34
  74. package/app-dist/pages/layout.html +0 -30
  75. package/app-dist/pages/modals.html +0 -21
  76. package/app-dist/pages/navbar.html +0 -22
  77. package/app-dist/pages/progress.html +0 -35
  78. package/app-dist/pages/radios.html +0 -40
  79. package/app-dist/pages/switches.html +0 -39
  80. package/app-dist/pages/tabs.html +0 -30
  81. package/app-dist/pages/toasts.html +0 -22
  82. package/app-dist/pages.json +0 -217
  83. package/app-dist/routes/alerts.js +0 -5
  84. package/app-dist/routes/avatars.js +0 -1
  85. package/app-dist/routes/badges.js +0 -1
  86. package/app-dist/routes/buttons.js +0 -1
  87. package/app-dist/routes/cards.js +0 -1
  88. package/app-dist/routes/checkboxes.js +0 -9
  89. package/app-dist/routes/chips.js +0 -4
  90. package/app-dist/routes/chunk-019e5e2f.js +0 -5
  91. package/app-dist/routes/chunk-0m4j19yd.js +0 -2
  92. package/app-dist/routes/chunk-0tmmp5q0.js +0 -1
  93. package/app-dist/routes/chunk-10xn709r.js +0 -1
  94. package/app-dist/routes/chunk-15m2qcda.js +0 -2
  95. package/app-dist/routes/chunk-1bh8g23n.js +0 -1
  96. package/app-dist/routes/chunk-1vg0v937.js +0 -1
  97. package/app-dist/routes/chunk-1zvcgy3j.js +0 -1
  98. package/app-dist/routes/chunk-2afb0861.js +0 -1
  99. package/app-dist/routes/chunk-2c6ttpzt.js +0 -5
  100. package/app-dist/routes/chunk-3dy30fhs.js +0 -1
  101. package/app-dist/routes/chunk-426dnces.js +0 -13
  102. package/app-dist/routes/chunk-44kgxery.js +0 -1
  103. package/app-dist/routes/chunk-47fdnejd.js +0 -33
  104. package/app-dist/routes/chunk-49a6t2vq.js +0 -1
  105. package/app-dist/routes/chunk-4fe1rm5b.js +0 -1
  106. package/app-dist/routes/chunk-4ggmvkta.js +0 -33
  107. package/app-dist/routes/chunk-4vkz81q7.js +0 -33
  108. package/app-dist/routes/chunk-4w4tmj8f.js +0 -31
  109. package/app-dist/routes/chunk-532s62kr.js +0 -31
  110. package/app-dist/routes/chunk-5hm3bssy.js +0 -33
  111. package/app-dist/routes/chunk-5vrh24hc.js +0 -1
  112. package/app-dist/routes/chunk-61pcg25a.js +0 -1
  113. package/app-dist/routes/chunk-6nfhygvf.js +0 -1
  114. package/app-dist/routes/chunk-700e7je6.js +0 -33
  115. package/app-dist/routes/chunk-7fsn17kg.js +0 -1
  116. package/app-dist/routes/chunk-7k789b32.js +0 -1
  117. package/app-dist/routes/chunk-7r46q0ys.js +0 -36
  118. package/app-dist/routes/chunk-86fmc1fr.js +0 -5
  119. package/app-dist/routes/chunk-8qth37vw.js +0 -1
  120. package/app-dist/routes/chunk-924wv8n0.js +0 -1
  121. package/app-dist/routes/chunk-9mbhgxk9.js +0 -1
  122. package/app-dist/routes/chunk-a216hyd9.js +0 -1
  123. package/app-dist/routes/chunk-akzxykh9.js +0 -33
  124. package/app-dist/routes/chunk-b3dcvy8c.js +0 -1
  125. package/app-dist/routes/chunk-b74zahz5.js +0 -31
  126. package/app-dist/routes/chunk-bftj53p2.js +0 -5
  127. package/app-dist/routes/chunk-c01hnz3e.js +0 -1
  128. package/app-dist/routes/chunk-d8pvv5km.js +0 -1
  129. package/app-dist/routes/chunk-dev0aezr.js +0 -2
  130. package/app-dist/routes/chunk-dh6vnv0e.js +0 -1
  131. package/app-dist/routes/chunk-dn2cbpva.js +0 -36
  132. package/app-dist/routes/chunk-dvn0my90.js +0 -1
  133. package/app-dist/routes/chunk-dvq8mnve.js +0 -36
  134. package/app-dist/routes/chunk-e8c2gc4d.js +0 -5
  135. package/app-dist/routes/chunk-ejf9ak2x.js +0 -1
  136. package/app-dist/routes/chunk-f083m55s.js +0 -1
  137. package/app-dist/routes/chunk-fnrj28s1.js +0 -31
  138. package/app-dist/routes/chunk-fvg3yjdp.js +0 -31
  139. package/app-dist/routes/chunk-g7k381n1.js +0 -1
  140. package/app-dist/routes/chunk-h01kq2ae.js +0 -13
  141. package/app-dist/routes/chunk-h4dk761v.js +0 -5
  142. package/app-dist/routes/chunk-hmx91z2x.js +0 -5
  143. package/app-dist/routes/chunk-hxbg4m42.js +0 -36
  144. package/app-dist/routes/chunk-jbjnfp2b.js +0 -2
  145. package/app-dist/routes/chunk-jxtz5vv6.js +0 -36
  146. package/app-dist/routes/chunk-jxzcs0ey.js +0 -36
  147. package/app-dist/routes/chunk-kt7wwhcx.js +0 -1
  148. package/app-dist/routes/chunk-kzptszyc.js +0 -33
  149. package/app-dist/routes/chunk-mhgca4w4.js +0 -2
  150. package/app-dist/routes/chunk-mhswxa20.js +0 -1
  151. package/app-dist/routes/chunk-n8zfeex6.js +0 -1
  152. package/app-dist/routes/chunk-pee47b2r.js +0 -1
  153. package/app-dist/routes/chunk-pesmw829.js +0 -1
  154. package/app-dist/routes/chunk-pgc4c6f3.js +0 -36
  155. package/app-dist/routes/chunk-q8egegm1.js +0 -1
  156. package/app-dist/routes/chunk-q9mn2qyq.js +0 -36
  157. package/app-dist/routes/chunk-qh0rtaf3.js +0 -5
  158. package/app-dist/routes/chunk-qqhmk6ye.js +0 -2
  159. package/app-dist/routes/chunk-qrxygmf7.js +0 -33
  160. package/app-dist/routes/chunk-r46yzksx.js +0 -36
  161. package/app-dist/routes/chunk-rgpbw2w0.js +0 -5
  162. package/app-dist/routes/chunk-rnpzv3d8.js +0 -2
  163. package/app-dist/routes/chunk-s5v8cv05.js +0 -2
  164. package/app-dist/routes/chunk-sbwn5bpc.js +0 -1
  165. package/app-dist/routes/chunk-sqbg8jbt.js +0 -33
  166. package/app-dist/routes/chunk-sv8dqnf7.js +0 -1
  167. package/app-dist/routes/chunk-t67sw3za.js +0 -1
  168. package/app-dist/routes/chunk-tjdpqwdf.js +0 -31
  169. package/app-dist/routes/chunk-tq2mfghg.js +0 -1
  170. package/app-dist/routes/chunk-ttn10vt6.js +0 -1
  171. package/app-dist/routes/chunk-v2hzpjxr.js +0 -1
  172. package/app-dist/routes/chunk-wfjjkw9y.js +0 -1
  173. package/app-dist/routes/chunk-wt8cxzmf.js +0 -31
  174. package/app-dist/routes/chunk-x45d372k.js +0 -5
  175. package/app-dist/routes/chunk-y3wsazkt.js +0 -1
  176. package/app-dist/routes/chunk-y7pmgc7t.js +0 -33
  177. package/app-dist/routes/chunk-zefdt2q3.js +0 -31
  178. package/app-dist/routes/dropdowns.js +0 -6
  179. package/app-dist/routes/home.js +0 -1
  180. package/app-dist/routes/icons.js +0 -1
  181. package/app-dist/routes/inputs.js +0 -12
  182. package/app-dist/routes/installation.js +0 -1
  183. package/app-dist/routes/layout.js +0 -1
  184. package/app-dist/routes/modals.js +0 -7
  185. package/app-dist/routes/navbar.js +0 -1
  186. package/app-dist/routes/progress.js +0 -1
  187. package/app-dist/routes/radios.js +0 -6
  188. package/app-dist/routes/switches.js +0 -6
  189. package/app-dist/routes/tabs.js +0 -1
  190. package/app-dist/routes/toasts.js +0 -16
  191. package/assets/fonts/material-symbols-mini.woff2 +0 -0
  192. package/assets/fonts/material-symbols.woff2 +0 -0
  193. package/assets/fonts/roboto-400.woff2 +0 -0
  194. package/assets/fonts/roboto-500.woff2 +0 -0
  195. package/assets/fonts/roboto-700.woff2 +0 -0
  196. package/assets/logo-banner-400.jpg +0 -0
  197. package/assets/logo-banner-400.webp +0 -0
  198. package/assets/logo-banner-800.webp +0 -0
  199. package/assets/logo-banner.jpg +0 -0
  200. package/assets/logo-icon-64.jpg +0 -0
  201. package/assets/logo-icon-64.webp +0 -0
  202. package/assets/logo-icon.jpg +0 -0
  203. package/assets/logo-square.jpg +0 -0
  204. package/bun.lock +0 -312
  205. package/bunfig.toml +0 -4
  206. package/custom-elements.json +0 -1916
  207. package/demo/api/sample-data.json +0 -38
  208. package/demo/content/alerts.html +0 -115
  209. package/demo/content/avatars.html +0 -70
  210. package/demo/content/badges.html +0 -65
  211. package/demo/content/buttons.html +0 -188
  212. package/demo/content/callouts.html +0 -91
  213. package/demo/content/cards.html +0 -121
  214. package/demo/content/checkboxes.html +0 -178
  215. package/demo/content/chips.html +0 -67
  216. package/demo/content/codeblocks.html +0 -101
  217. package/demo/content/confirms.html +0 -115
  218. package/demo/content/datatables.html +0 -149
  219. package/demo/content/dividers.html +0 -119
  220. package/demo/content/dropdowns.html +0 -89
  221. package/demo/content/enterprise.html +0 -252
  222. package/demo/content/home.html +0 -149
  223. package/demo/content/icons.html +0 -89
  224. package/demo/content/inputs.html +0 -135
  225. package/demo/content/installation.html +0 -16
  226. package/demo/content/layout.html +0 -136
  227. package/demo/content/modals.html +0 -141
  228. package/demo/content/navbar.html +0 -70
  229. package/demo/content/progress.html +0 -119
  230. package/demo/content/radios.html +0 -88
  231. package/demo/content/skeletons.html +0 -109
  232. package/demo/content/spinners.html +0 -96
  233. package/demo/content/switches.html +0 -84
  234. package/demo/content/tables.html +0 -124
  235. package/demo/content/tabs.html +0 -85
  236. package/demo/content/toasts.html +0 -116
  237. package/demo/content/tooltips.html +0 -107
  238. package/demo/content/virtual-lists.html +0 -233
  239. package/demo/favicon.ico +0 -0
  240. package/demo/favicon.png +0 -0
  241. package/demo/full.html +0 -52
  242. package/demo/iife.html +0 -46
  243. package/demo/manifest.json +0 -34
  244. package/demo/pages/datatable-demo.html +0 -237
  245. package/demo/pages/prompt-ui-demo.html +0 -218
  246. package/demo/pages/responsive-demo.html +0 -122
  247. package/demo/pages/schema-form-demo.html +0 -270
  248. package/demo/robots.txt +0 -6
  249. package/demo/shell.html +0 -712
  250. package/demo/sw.js +0 -387
  251. package/lighthouse-audit.mjs +0 -113
  252. package/scripts/analyze-components.js +0 -105
  253. package/scripts/build-app.js +0 -193
  254. package/scripts/build-framework.js +0 -444
  255. package/scripts/build-utils.js +0 -101
  256. package/scripts/test-isolated.js +0 -151
  257. package/server.js +0 -256
  258. package/tests/agents/agent-integration.test.js +0 -76
  259. package/tests/benchmark.html +0 -296
  260. package/tests/build/scan-components.test.js +0 -173
  261. package/tests/components/all-components.test.js +0 -245
  262. package/tests/components/all-missing-components.test.js +0 -574
  263. package/tests/components/mu-alert.test.js +0 -113
  264. package/tests/components/mu-avatar.test.js +0 -148
  265. package/tests/components/mu-badge.test.js +0 -92
  266. package/tests/components/mu-button.test.js +0 -112
  267. package/tests/components/mu-card.test.js +0 -89
  268. package/tests/components/mu-checkbox.test.js +0 -158
  269. package/tests/components/mu-chip.test.js +0 -118
  270. package/tests/components/mu-container.test.js +0 -120
  271. package/tests/components/mu-divider.test.js +0 -98
  272. package/tests/components/mu-drawer-item.test.js +0 -199
  273. package/tests/components/mu-drawer.test.js +0 -96
  274. package/tests/components/mu-dropdown.test.js +0 -125
  275. package/tests/components/mu-form.test.js +0 -138
  276. package/tests/components/mu-grid.test.js +0 -135
  277. package/tests/components/mu-icon.test.js +0 -110
  278. package/tests/components/mu-input.test.js +0 -131
  279. package/tests/components/mu-lazy.test.js +0 -103
  280. package/tests/components/mu-modal.test.js +0 -275
  281. package/tests/components/mu-navbar.test.js +0 -101
  282. package/tests/components/mu-progress.test.js +0 -115
  283. package/tests/components/mu-radio.test.js +0 -114
  284. package/tests/components/mu-repeat.test.js +0 -106
  285. package/tests/components/mu-sidebar.test.js +0 -126
  286. package/tests/components/mu-skeleton.test.js +0 -162
  287. package/tests/components/mu-stack.test.js +0 -143
  288. package/tests/components/mu-switch.test.js +0 -292
  289. package/tests/components/mu-table.test.js +0 -124
  290. package/tests/components/mu-tabs.test.js +0 -104
  291. package/tests/components/mu-textarea.test.js +0 -115
  292. package/tests/components/mu-toast.test.js +0 -321
  293. package/tests/components/mu-tooltip.test.js +0 -133
  294. package/tests/components/mu-virtual-list.test.js +0 -109
  295. package/tests/core/MuElement.test.js +0 -120
  296. package/tests/core/agent-api.test.js +0 -125
  297. package/tests/core/all-core-modules.test.js +0 -442
  298. package/tests/core/bus.test.js +0 -364
  299. package/tests/core/component-schema.test.js +0 -160
  300. package/tests/core/feature-registry.test.js +0 -198
  301. package/tests/core/form-state.test.js +0 -167
  302. package/tests/core/http.test.js +0 -119
  303. package/tests/core/keyboard.test.js +0 -319
  304. package/tests/core/layers.test.js +0 -129
  305. package/tests/core/namespaced-stores.test.js +0 -114
  306. package/tests/core/render.test.js +0 -121
  307. package/tests/core/ripple.test.js +0 -131
  308. package/tests/core/router.test.js +0 -89
  309. package/tests/core/scheduler.test.js +0 -121
  310. package/tests/core/signals.test.js +0 -128
  311. package/tests/core/store.test.js +0 -171
  312. package/tests/core/transitions.test.js +0 -82
  313. package/tests/e2e/accessibility-harness.html +0 -58
  314. package/tests/e2e/accessibility.test.js +0 -401
  315. package/tests/e2e/agent-features.test.js +0 -372
  316. package/tests/e2e/card-spacing.test.js +0 -287
  317. package/tests/e2e/components.test.js +0 -439
  318. package/tests/e2e/demo-routes.test.js +0 -478
  319. package/tests/e2e/layout-css-fallback.test.js +0 -334
  320. package/tests/e2e/mu-alert.e2e.test.js +0 -111
  321. package/tests/e2e/mu-checkbox.test.js +0 -489
  322. package/tests/e2e/mu-chip.test.js +0 -347
  323. package/tests/e2e/mu-form.test.js +0 -499
  324. package/tests/e2e/mu-icon.test.js +0 -114
  325. package/tests/e2e/mu-radio.test.js +0 -113
  326. package/tests/e2e/mu-skeleton.test.js +0 -140
  327. package/tests/e2e/mu-switch.test.js +0 -415
  328. package/tests/e2e/mu-tabs.test.js +0 -494
  329. package/tests/e2e/mu-textarea.test.js +0 -242
  330. package/tests/e2e/mu-virtual-list.test.js +0 -427
  331. package/tests/e2e/perf-memory.test.js +0 -161
  332. package/tests/e2e/puppeteer-helper.js +0 -137
  333. package/tests/e2e/puppeteer.test.js +0 -226
  334. package/tests/e2e/pwa.test.js +0 -261
  335. package/tests/e2e/test-harness.html +0 -319
  336. package/tests/manual/test-components.html +0 -120
  337. package/tests/memory-test.html +0 -309
  338. package/tests/setup-dom.js +0 -93
  339. package/tests/visual-test.html +0 -301
@@ -1,103 +0,0 @@
1
- /**
2
- * @fileoverview Unit Tests for mu-lazy Component
3
- * Target: 94% → maintain/improve
4
- */
5
-
6
- import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
7
- import { parseHTML } from 'linkedom';
8
-
9
- let document, customElements, body;
10
- let MuLazy;
11
-
12
- // Mock IntersectionObserver
13
- class MockIntersectionObserver {
14
- constructor(callback) {
15
- this.callback = callback;
16
- }
17
- observe() { }
18
- unobserve() { }
19
- disconnect() { }
20
- }
21
-
22
- describe('mu-lazy Unit Tests', () => {
23
-
24
- beforeAll(async () => {
25
- const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
26
- document = dom.document;
27
- customElements = dom.customElements;
28
- body = document.body;
29
-
30
- globalThis.window = dom.window;
31
- globalThis.document = document;
32
- globalThis.customElements = customElements;
33
- globalThis.HTMLElement = dom.HTMLElement;
34
- globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
35
- globalThis.IntersectionObserver = MockIntersectionObserver;
36
-
37
- const module = await import('../../src/components/mu-lazy.js');
38
- MuLazy = module.MuLazy;
39
- });
40
-
41
- beforeEach(() => { body.innerHTML = ''; });
42
-
43
- // REGISTRATION
44
- test('should be registered', () => {
45
- expect(customElements.get('mu-lazy')).toBe(MuLazy);
46
- });
47
-
48
- test('should have correct baseClass', () => {
49
- expect(MuLazy.baseClass).toBe('mu-lazy');
50
- });
51
-
52
- test('should observe root-margin, threshold', () => {
53
- expect(MuLazy.observedAttributes).toContain('root-margin');
54
- expect(MuLazy.observedAttributes).toContain('threshold');
55
- });
56
-
57
- // RENDER
58
- test('should render without errors', () => {
59
- const el = document.createElement('mu-lazy');
60
- body.appendChild(el);
61
- el.render(); // linkedom doesn't auto-call connectedCallback
62
- expect(el.classList.contains('mu-lazy')).toBe(true);
63
- });
64
-
65
- test('render should be idempotent', () => {
66
- const el = document.createElement('mu-lazy');
67
- body.appendChild(el);
68
- el.render();
69
- expect(true).toBe(true);
70
- });
71
-
72
- // LOAD
73
- test('should have load method', () => {
74
- const el = document.createElement('mu-lazy');
75
- body.appendChild(el);
76
- expect(typeof el.load).toBe('function');
77
- });
78
-
79
- // SRC
80
- test('should support src attribute', () => {
81
- const el = document.createElement('mu-lazy');
82
- el.setAttribute('src', 'image.jpg');
83
- body.appendChild(el);
84
- expect(el.getAttribute('src')).toBe('image.jpg');
85
- });
86
-
87
- // THRESHOLD
88
- test('should support threshold attribute', () => {
89
- const el = document.createElement('mu-lazy');
90
- el.setAttribute('threshold', '0.5');
91
- body.appendChild(el);
92
- expect(el.getAttribute('threshold')).toBe('0.5');
93
- });
94
-
95
- // LOADED STATE
96
- test('should have loaded property', () => {
97
- const el = document.createElement('mu-lazy');
98
- body.appendChild(el);
99
- el.render(); // linkedom doesn't auto-call connectedCallback
100
- // loaded may be undefined before render, or boolean after
101
- expect(el.loaded === undefined || typeof el.loaded === 'boolean').toBe(true);
102
- });
103
- });
@@ -1,275 +0,0 @@
1
- /**
2
- * @fileoverview Unit Tests for mu-modal Component (Native Dialog)
3
- *
4
- * CRITICAL: These tests prevent regressions for:
5
- * - Open/Close functionality via native dialog
6
- * - X button click handler
7
- * - ESC key (native cancel event)
8
- * - DOM structure with <dialog> element
9
- * - Events (mu-open, mu-close)
10
- * - Visibility states
11
- */
12
-
13
- import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
14
-
15
- // Setup linkedom for DOM testing
16
- import { parseHTML } from 'linkedom';
17
-
18
- let document, customElements, HTMLElement, body;
19
- let MuModal;
20
-
21
- describe('mu-modal Component', () => {
22
-
23
- beforeAll(async () => {
24
- const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
25
- document = dom.document;
26
- customElements = dom.customElements;
27
- HTMLElement = dom.HTMLElement;
28
- body = document.body;
29
-
30
- globalThis.document = document;
31
- globalThis.customElements = customElements;
32
- globalThis.HTMLElement = HTMLElement;
33
- globalThis.CustomEvent = class CustomEvent extends Event {
34
- constructor(type, options = {}) {
35
- super(type, options);
36
- this.detail = options.detail;
37
- }
38
- };
39
-
40
- // Polyfill requestAnimationFrame for linkedom
41
- globalThis.requestAnimationFrame = (cb) => {
42
- cb(Date.now());
43
- return 0;
44
- };
45
-
46
- // Import component (this also registers it)
47
- const module = await import('../../src/components/mu-modal.js');
48
- MuModal = module.MuModal;
49
-
50
- // Patch emit for linkedom compatibility
51
- MuModal.prototype.emit = function (eventName, detail) {
52
- try {
53
- this.dispatchEvent(new Event(eventName, { bubbles: true }));
54
- } catch (e) {
55
- // linkedom throws on eventPhase assignment
56
- }
57
- };
58
-
59
- // Polyfill: wrap render to add showModal/close to dialog
60
- // linkedom doesn't support native dialog methods (created via innerHTML)
61
- const originalRender = MuModal.prototype.render;
62
- MuModal.prototype.render = function () {
63
- originalRender.call(this);
64
- const dialog = this.querySelector('dialog');
65
- if (dialog && !dialog.showModal) {
66
- dialog.open = false;
67
- dialog.showModal = function () {
68
- this.open = true;
69
- this.setAttribute('open', '');
70
- };
71
- dialog.close = function () {
72
- this.open = false;
73
- this.removeAttribute('open');
74
- try {
75
- this.dispatchEvent(new Event('close'));
76
- } catch (e) {
77
- // linkedom event dispatch can fail
78
- }
79
- };
80
- }
81
- };
82
- });
83
-
84
- beforeEach(() => {
85
- body.innerHTML = '';
86
- document.body.style.overflow = '';
87
- });
88
-
89
- // ============================================================
90
- // REGISTRATION AND BASE SETUP
91
- // ============================================================
92
-
93
- test('mu-modal should be registered as custom element', () => {
94
- expect(customElements.get('mu-modal')).toBe(MuModal);
95
- });
96
-
97
- test('mu-modal should have correct baseClass', () => {
98
- expect(MuModal.baseClass).toBe('mu-modal');
99
- });
100
-
101
- test('mu-modal should observe open and size attributes', () => {
102
- expect(MuModal.observedAttributes).toContain('open');
103
- expect(MuModal.observedAttributes).toContain('size');
104
- });
105
-
106
- // ============================================================
107
- // DOM STRUCTURE - Native <dialog> element
108
- // ============================================================
109
-
110
- test('mu-modal should render with base class', () => {
111
- const modal = document.createElement('mu-modal');
112
- modal.innerHTML = '<p>Test content</p>';
113
- body.appendChild(modal);
114
-
115
- expect(modal.classList.contains('mu-modal')).toBe(true);
116
- });
117
-
118
- test('mu-modal should create native dialog element', () => {
119
- const modal = document.createElement('mu-modal');
120
- modal.innerHTML = '<p>Test content</p>';
121
- body.appendChild(modal);
122
-
123
- const dialog = modal.querySelector('dialog');
124
- expect(dialog).not.toBeNull();
125
- expect(dialog.classList.contains('mu-modal__dialog')).toBe(true);
126
- });
127
-
128
- test('mu-modal should create close button', () => {
129
- const modal = document.createElement('mu-modal');
130
- modal.innerHTML = '<p>Test content</p>';
131
- body.appendChild(modal);
132
-
133
- const closeBtn = modal.querySelector('.mu-modal__close');
134
- expect(closeBtn).not.toBeNull();
135
- expect(closeBtn.getAttribute('aria-label')).toBe('Close');
136
- });
137
-
138
- test('mu-modal should preserve user content in body', () => {
139
- const modal = document.createElement('mu-modal');
140
- modal.innerHTML = '<p class="user-content">Test content</p>';
141
- body.appendChild(modal);
142
-
143
- const contentBody = modal.querySelector('.mu-modal__body');
144
- expect(contentBody).not.toBeNull();
145
- expect(contentBody.innerHTML).toContain('Test content');
146
- });
147
-
148
- test('mu-modal should have exactly ONE dialog (no nesting)', () => {
149
- const modal = document.createElement('mu-modal');
150
- modal.innerHTML = '<p>Test content</p>';
151
- body.appendChild(modal);
152
-
153
- const dialogs = modal.querySelectorAll('dialog');
154
- expect(dialogs.length).toBe(1);
155
- });
156
-
157
- // ============================================================
158
- // OPEN/CLOSE FUNCTIONALITY
159
- // ============================================================
160
-
161
- test('mu-modal should be hidden by default (no is-open class)', () => {
162
- const modal = document.createElement('mu-modal');
163
- modal.innerHTML = '<p>Test content</p>';
164
- body.appendChild(modal);
165
-
166
- expect(modal.classList.contains('is-open')).toBe(false);
167
- });
168
-
169
- test('mu-modal.open() should set open attribute', () => {
170
- const modal = document.createElement('mu-modal');
171
- modal.innerHTML = '<p>Test content</p>';
172
- body.appendChild(modal);
173
-
174
- modal.open();
175
- expect(modal.hasAttribute('open')).toBe(true);
176
- });
177
-
178
- test('mu-modal.close() should remove open attribute after animation', async () => {
179
- const modal = document.createElement('mu-modal');
180
- modal.innerHTML = '<p>Test content</p>';
181
- body.appendChild(modal);
182
-
183
- modal.open();
184
- modal.close();
185
-
186
- // Wait for exit animation (200ms + buffer)
187
- await new Promise(r => setTimeout(r, 250));
188
- expect(modal.hasAttribute('open')).toBe(false);
189
- });
190
-
191
- // ============================================================
192
- // CLOSE BUTTON - CRITICAL REGRESSION TEST
193
- // ============================================================
194
-
195
- test('clicking close button should close the modal', async () => {
196
- const modal = document.createElement('mu-modal');
197
- modal.innerHTML = '<p>Test content</p>';
198
- body.appendChild(modal);
199
-
200
- modal.open();
201
-
202
- const closeBtn = modal.querySelector('.mu-modal__close');
203
- closeBtn.click();
204
-
205
- // Wait for exit animation (200ms + buffer)
206
- await new Promise(r => setTimeout(r, 250));
207
- expect(modal.hasAttribute('open')).toBe(false);
208
- });
209
-
210
- // ============================================================
211
- // SIZE VARIANTS
212
- // ============================================================
213
-
214
- test('mu-modal should apply size attribute to dialog', () => {
215
- const modal = document.createElement('mu-modal');
216
- modal.setAttribute('size', 'lg');
217
- modal.innerHTML = '<p>Test content</p>';
218
- body.appendChild(modal);
219
-
220
- const dialog = modal.querySelector('dialog');
221
- expect(dialog.classList.contains('mu-modal--lg')).toBe(true);
222
- });
223
-
224
- test('mu-modal should default to md size', () => {
225
- const modal = document.createElement('mu-modal');
226
- modal.innerHTML = '<p>Test content</p>';
227
- body.appendChild(modal);
228
-
229
- const dialog = modal.querySelector('dialog');
230
- expect(dialog.classList.contains('mu-modal--md')).toBe(true);
231
- });
232
-
233
- // ============================================================
234
- // IDEMPOTENT RENDERING
235
- // ============================================================
236
-
237
- test('multiple opens should not duplicate internal elements', async () => {
238
- const modal = document.createElement('mu-modal');
239
- modal.innerHTML = '<p>Test content</p>';
240
- body.appendChild(modal);
241
-
242
- modal.open();
243
- modal.close();
244
- await new Promise(r => setTimeout(r, 350));
245
- modal.open();
246
- modal.close();
247
- await new Promise(r => setTimeout(r, 350));
248
- modal.open();
249
-
250
- const dialogs = modal.querySelectorAll('dialog');
251
- expect(dialogs.length).toBe(1);
252
- });
253
-
254
- // ============================================================
255
- // NO TELEPORTATION - Native dialog handles top-layer
256
- // ============================================================
257
-
258
- test('mu-modal should NOT teleport to body (native dialog handles top-layer)', () => {
259
- const container = document.createElement('div');
260
- container.id = 'app';
261
- body.appendChild(container);
262
-
263
- const modal = document.createElement('mu-modal');
264
- modal.innerHTML = '<p>Test content</p>';
265
- container.appendChild(modal);
266
-
267
- // Modal stays in container
268
- expect(modal.parentElement).toBe(container);
269
-
270
- modal.open();
271
-
272
- // Still in container - native dialog handles top-layer
273
- expect(modal.parentElement).toBe(container);
274
- });
275
- });
@@ -1,101 +0,0 @@
1
- /**
2
- * @fileoverview Unit Tests for mu-navbar Component Suite
3
- * Target: 87% → 100%
4
- */
5
-
6
- import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
7
- import { parseHTML } from 'linkedom';
8
-
9
- let document, customElements, body;
10
- let MuNavbar, MuNavbarBrand, MuNavbarLinks, MuNavbarActions;
11
-
12
- describe('mu-navbar Unit Tests', () => {
13
-
14
- beforeAll(async () => {
15
- const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
16
- document = dom.document;
17
- customElements = dom.customElements;
18
- body = document.body;
19
-
20
- globalThis.window = dom.window;
21
- globalThis.document = document;
22
- globalThis.customElements = customElements;
23
- globalThis.HTMLElement = dom.HTMLElement;
24
- globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
25
-
26
- const module = await import('../../src/components/mu-navbar.js');
27
- MuNavbar = module.MuNavbar;
28
- MuNavbarBrand = module.MuNavbarBrand;
29
- MuNavbarLinks = module.MuNavbarLinks;
30
- MuNavbarActions = module.MuNavbarActions;
31
- });
32
-
33
- beforeEach(() => { body.innerHTML = ''; });
34
-
35
- // NAVBAR
36
- test('MuNavbar should be registered', () => {
37
- expect(customElements.get('mu-navbar')).toBe(MuNavbar);
38
- });
39
-
40
- test('MuNavbar should have correct baseClass', () => {
41
- expect(MuNavbar.baseClass).toBe('mu-navbar');
42
- });
43
-
44
- test('MuNavbar should observe sticky and variant', () => {
45
- expect(MuNavbar.observedAttributes).toContain('sticky');
46
- expect(MuNavbar.observedAttributes).toContain('variant');
47
- });
48
-
49
- test('MuNavbar should set display flex', () => {
50
- const el = document.createElement('mu-navbar');
51
- body.appendChild(el);
52
- expect(el.style.display).toBe('flex');
53
- });
54
-
55
- test('MuNavbar should set height 64px', () => {
56
- const el = document.createElement('mu-navbar');
57
- body.appendChild(el);
58
- expect(el.style.height).toBe('64px');
59
- });
60
-
61
- test('MuNavbar sticky should set position sticky', () => {
62
- const el = document.createElement('mu-navbar');
63
- el.setAttribute('sticky', '');
64
- body.appendChild(el);
65
- expect(el.style.position).toBe('sticky');
66
- });
67
-
68
- test('MuNavbar sticky should set zIndex', () => {
69
- const el = document.createElement('mu-navbar');
70
- el.setAttribute('sticky', '');
71
- body.appendChild(el);
72
- expect(el.style.zIndex).toBe('100');
73
- });
74
-
75
- // NAVBAR BRAND
76
- test('MuNavbarBrand should be registered', () => {
77
- expect(customElements.get('mu-navbar-brand')).toBe(MuNavbarBrand);
78
- });
79
-
80
- test('MuNavbarBrand should set fontWeight', () => {
81
- const el = document.createElement('mu-navbar-brand');
82
- body.appendChild(el);
83
- expect(el.style.fontWeight).toBe('600');
84
- });
85
-
86
- // NAVBAR LINKS
87
- test('MuNavbarLinks should be registered', () => {
88
- expect(customElements.get('mu-navbar-links')).toBe(MuNavbarLinks);
89
- });
90
-
91
- // NAVBAR ACTIONS
92
- test('MuNavbarActions should be registered', () => {
93
- expect(customElements.get('mu-navbar-actions')).toBe(MuNavbarActions);
94
- });
95
-
96
- test('MuNavbarActions should set display flex', () => {
97
- const el = document.createElement('mu-navbar-actions');
98
- body.appendChild(el);
99
- expect(el.style.display).toBe('flex');
100
- });
101
- });
@@ -1,115 +0,0 @@
1
- /**
2
- * @fileoverview Unit Tests for mu-progress Component
3
- * Target: 88% → 100% coverage
4
- */
5
-
6
- import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
7
- import { parseHTML } from 'linkedom';
8
-
9
- let document, customElements, body;
10
- let MuProgress;
11
-
12
- describe('mu-progress Unit Tests', () => {
13
-
14
- beforeAll(async () => {
15
- const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
16
- document = dom.document;
17
- customElements = dom.customElements;
18
- body = document.body;
19
-
20
- globalThis.window = dom.window;
21
- globalThis.document = document;
22
- globalThis.customElements = customElements;
23
- globalThis.HTMLElement = dom.HTMLElement;
24
- globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
25
-
26
- const module = await import('../../src/components/mu-progress.js');
27
- MuProgress = module.MuProgress;
28
- });
29
-
30
- beforeEach(() => { body.innerHTML = ''; });
31
-
32
- // REGISTRATION
33
- test('should be registered', () => {
34
- expect(customElements.get('mu-progress')).toBe(MuProgress);
35
- });
36
-
37
- test('should have correct baseClass', () => {
38
- expect(MuProgress.baseClass).toBe('mu-progress');
39
- });
40
-
41
- test('should observe value, max, variant', () => {
42
- expect(MuProgress.observedAttributes).toContain('value');
43
- expect(MuProgress.observedAttributes).toContain('max');
44
- expect(MuProgress.observedAttributes).toContain('variant');
45
- });
46
-
47
- // RENDER
48
- test('should create progress bar element', () => {
49
- const el = document.createElement('mu-progress');
50
- body.appendChild(el);
51
- expect(el.querySelector('.mu-progress__bar')).not.toBeNull();
52
- });
53
-
54
- test('should set role progressbar', () => {
55
- const el = document.createElement('mu-progress');
56
- body.appendChild(el);
57
- expect(el.getAttribute('role')).toBe('progressbar');
58
- });
59
-
60
- test('should be idempotent', () => {
61
- const el = document.createElement('mu-progress');
62
- body.appendChild(el);
63
- el.render();
64
- expect(el.querySelectorAll('.mu-progress__bar').length).toBe(1);
65
- });
66
-
67
- // VALUE
68
- test('should set aria-valuenow', () => {
69
- const el = document.createElement('mu-progress');
70
- el.setAttribute('value', '50');
71
- body.appendChild(el);
72
- expect(el.getAttribute('aria-valuenow')).toBe('50');
73
- });
74
-
75
- test('should set aria-valuemax', () => {
76
- const el = document.createElement('mu-progress');
77
- el.setAttribute('max', '200');
78
- body.appendChild(el);
79
- expect(el.getAttribute('aria-valuemax')).toBe('200');
80
- });
81
-
82
- test('should update bar width based on value', () => {
83
- const el = document.createElement('mu-progress');
84
- el.setAttribute('value', '25');
85
- el.setAttribute('max', '100');
86
- body.appendChild(el);
87
- const bar = el.querySelector('.mu-progress__bar');
88
- expect(bar.style.width).toBe('25%');
89
- });
90
-
91
- test('should clamp value to 100%', () => {
92
- const el = document.createElement('mu-progress');
93
- el.setAttribute('value', '150');
94
- body.appendChild(el);
95
- const bar = el.querySelector('.mu-progress__bar');
96
- expect(bar.style.width).toBe('100%');
97
- });
98
-
99
- // VARIANT
100
- test('should apply variant class', () => {
101
- const el = document.createElement('mu-progress');
102
- el.setAttribute('variant', 'success');
103
- body.appendChild(el);
104
- expect(el.classList.contains('mu-progress--success')).toBe(true);
105
- });
106
-
107
- // UPDATE
108
- test('update should update progress on value change', () => {
109
- const el = document.createElement('mu-progress');
110
- body.appendChild(el);
111
- el.setAttribute('value', '75');
112
- el.update('value', '75', '0');
113
- expect(el.getAttribute('aria-valuenow')).toBe('75');
114
- });
115
- });