microui-wc 0.1.0 → 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.
- package/AGENTS.md +71 -71
- package/CHANGELOG.md +1 -1
- package/README.md +14 -9
- package/dist/AGENTS.md +116 -116
- package/dist/README.md +21 -16
- package/dist/components.css +1 -1
- package/dist/microui.css +1 -1
- package/dist/microui.esm.js.map +1 -1
- package/dist/microui.min.js.map +1 -1
- package/dist/styles/components/switch.css +1 -1
- package/docs/getting-started.md +3 -3
- package/package.json +38 -10
- package/src/components/mu-schema-form.js +1 -1
- package/src/styles/components/switch.css +7 -8
- package/src/styles/components.css +6 -6
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -33
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
- package/.github/workflows/ci.yml +0 -42
- package/.github/workflows/deploy-pages.yml +0 -112
- package/CODE_OF_CONDUCT.md +0 -59
- package/CONTRIBUTING.md +0 -156
- package/SECURITY.md +0 -58
- package/app/.generated/routes/alerts.js +0 -8
- package/app/.generated/routes/avatars.js +0 -8
- package/app/.generated/routes/badges.js +0 -8
- package/app/.generated/routes/buttons.js +0 -10
- package/app/.generated/routes/cards.js +0 -10
- package/app/.generated/routes/checkboxes.js +0 -9
- package/app/.generated/routes/chips.js +0 -8
- package/app/.generated/routes/dropdowns.js +0 -9
- package/app/.generated/routes/home.js +0 -7
- package/app/.generated/routes/icons.js +0 -9
- package/app/.generated/routes/inputs.js +0 -10
- package/app/.generated/routes/installation.js +0 -7
- package/app/.generated/routes/layout.js +0 -9
- package/app/.generated/routes/modals.js +0 -9
- package/app/.generated/routes/navbar.js +0 -7
- package/app/.generated/routes/progress.js +0 -9
- package/app/.generated/routes/radios.js +0 -9
- package/app/.generated/routes/switches.js +0 -9
- package/app/.generated/routes/tabs.js +0 -8
- package/app/.generated/routes/toasts.js +0 -9
- package/app/index.html +0 -67
- package/app/pages/alerts.html +0 -23
- package/app/pages/avatars.html +0 -22
- package/app/pages/badges.html +0 -22
- package/app/pages/buttons.html +0 -71
- package/app/pages/cards.html +0 -54
- package/app/pages/checkboxes.html +0 -39
- package/app/pages/chips.html +0 -23
- package/app/pages/dropdowns.html +0 -41
- package/app/pages/home.html +0 -59
- package/app/pages/icons.html +0 -29
- package/app/pages/inputs.html +0 -66
- package/app/pages/installation.html +0 -34
- package/app/pages/layout.html +0 -30
- package/app/pages/modals.html +0 -21
- package/app/pages/navbar.html +0 -22
- package/app/pages/progress.html +0 -35
- package/app/pages/radios.html +0 -40
- package/app/pages/switches.html +0 -39
- package/app/pages/tabs.html +0 -30
- package/app/pages/toasts.html +0 -22
- package/app-dist/index.html +0 -67
- package/app-dist/pages/alerts.html +0 -23
- package/app-dist/pages/avatars.html +0 -22
- package/app-dist/pages/badges.html +0 -22
- package/app-dist/pages/buttons.html +0 -71
- package/app-dist/pages/cards.html +0 -54
- package/app-dist/pages/checkboxes.html +0 -39
- package/app-dist/pages/chips.html +0 -23
- package/app-dist/pages/dropdowns.html +0 -41
- package/app-dist/pages/home.html +0 -59
- package/app-dist/pages/icons.html +0 -29
- package/app-dist/pages/inputs.html +0 -66
- package/app-dist/pages/installation.html +0 -34
- package/app-dist/pages/layout.html +0 -30
- package/app-dist/pages/modals.html +0 -21
- package/app-dist/pages/navbar.html +0 -22
- package/app-dist/pages/progress.html +0 -35
- package/app-dist/pages/radios.html +0 -40
- package/app-dist/pages/switches.html +0 -39
- package/app-dist/pages/tabs.html +0 -30
- package/app-dist/pages/toasts.html +0 -22
- package/app-dist/pages.json +0 -217
- package/app-dist/routes/alerts.js +0 -5
- package/app-dist/routes/avatars.js +0 -1
- package/app-dist/routes/badges.js +0 -1
- package/app-dist/routes/buttons.js +0 -1
- package/app-dist/routes/cards.js +0 -1
- package/app-dist/routes/checkboxes.js +0 -9
- package/app-dist/routes/chips.js +0 -4
- package/app-dist/routes/chunk-019e5e2f.js +0 -5
- package/app-dist/routes/chunk-0m4j19yd.js +0 -2
- package/app-dist/routes/chunk-0tmmp5q0.js +0 -1
- package/app-dist/routes/chunk-10xn709r.js +0 -1
- package/app-dist/routes/chunk-15m2qcda.js +0 -2
- package/app-dist/routes/chunk-1bh8g23n.js +0 -1
- package/app-dist/routes/chunk-1vg0v937.js +0 -1
- package/app-dist/routes/chunk-1zvcgy3j.js +0 -1
- package/app-dist/routes/chunk-2afb0861.js +0 -1
- package/app-dist/routes/chunk-2c6ttpzt.js +0 -5
- package/app-dist/routes/chunk-3dy30fhs.js +0 -1
- package/app-dist/routes/chunk-426dnces.js +0 -13
- package/app-dist/routes/chunk-44kgxery.js +0 -1
- package/app-dist/routes/chunk-47fdnejd.js +0 -33
- package/app-dist/routes/chunk-49a6t2vq.js +0 -1
- package/app-dist/routes/chunk-4fe1rm5b.js +0 -1
- package/app-dist/routes/chunk-4ggmvkta.js +0 -33
- package/app-dist/routes/chunk-4vkz81q7.js +0 -33
- package/app-dist/routes/chunk-4w4tmj8f.js +0 -31
- package/app-dist/routes/chunk-532s62kr.js +0 -31
- package/app-dist/routes/chunk-5hm3bssy.js +0 -33
- package/app-dist/routes/chunk-5vrh24hc.js +0 -1
- package/app-dist/routes/chunk-61pcg25a.js +0 -1
- package/app-dist/routes/chunk-6nfhygvf.js +0 -1
- package/app-dist/routes/chunk-700e7je6.js +0 -33
- package/app-dist/routes/chunk-7fsn17kg.js +0 -1
- package/app-dist/routes/chunk-7k789b32.js +0 -1
- package/app-dist/routes/chunk-7r46q0ys.js +0 -36
- package/app-dist/routes/chunk-86fmc1fr.js +0 -5
- package/app-dist/routes/chunk-8qth37vw.js +0 -1
- package/app-dist/routes/chunk-924wv8n0.js +0 -1
- package/app-dist/routes/chunk-9mbhgxk9.js +0 -1
- package/app-dist/routes/chunk-a216hyd9.js +0 -1
- package/app-dist/routes/chunk-akzxykh9.js +0 -33
- package/app-dist/routes/chunk-b3dcvy8c.js +0 -1
- package/app-dist/routes/chunk-b74zahz5.js +0 -31
- package/app-dist/routes/chunk-bftj53p2.js +0 -5
- package/app-dist/routes/chunk-c01hnz3e.js +0 -1
- package/app-dist/routes/chunk-d8pvv5km.js +0 -1
- package/app-dist/routes/chunk-dev0aezr.js +0 -2
- package/app-dist/routes/chunk-dh6vnv0e.js +0 -1
- package/app-dist/routes/chunk-dn2cbpva.js +0 -36
- package/app-dist/routes/chunk-dvn0my90.js +0 -1
- package/app-dist/routes/chunk-dvq8mnve.js +0 -36
- package/app-dist/routes/chunk-e8c2gc4d.js +0 -5
- package/app-dist/routes/chunk-ejf9ak2x.js +0 -1
- package/app-dist/routes/chunk-f083m55s.js +0 -1
- package/app-dist/routes/chunk-fnrj28s1.js +0 -31
- package/app-dist/routes/chunk-fvg3yjdp.js +0 -31
- package/app-dist/routes/chunk-g7k381n1.js +0 -1
- package/app-dist/routes/chunk-h01kq2ae.js +0 -13
- package/app-dist/routes/chunk-h4dk761v.js +0 -5
- package/app-dist/routes/chunk-hmx91z2x.js +0 -5
- package/app-dist/routes/chunk-hxbg4m42.js +0 -36
- package/app-dist/routes/chunk-jbjnfp2b.js +0 -2
- package/app-dist/routes/chunk-jxtz5vv6.js +0 -36
- package/app-dist/routes/chunk-jxzcs0ey.js +0 -36
- package/app-dist/routes/chunk-kt7wwhcx.js +0 -1
- package/app-dist/routes/chunk-kzptszyc.js +0 -33
- package/app-dist/routes/chunk-mhgca4w4.js +0 -2
- package/app-dist/routes/chunk-mhswxa20.js +0 -1
- package/app-dist/routes/chunk-n8zfeex6.js +0 -1
- package/app-dist/routes/chunk-pee47b2r.js +0 -1
- package/app-dist/routes/chunk-pesmw829.js +0 -1
- package/app-dist/routes/chunk-pgc4c6f3.js +0 -36
- package/app-dist/routes/chunk-q8egegm1.js +0 -1
- package/app-dist/routes/chunk-q9mn2qyq.js +0 -36
- package/app-dist/routes/chunk-qh0rtaf3.js +0 -5
- package/app-dist/routes/chunk-qqhmk6ye.js +0 -2
- package/app-dist/routes/chunk-qrxygmf7.js +0 -33
- package/app-dist/routes/chunk-r46yzksx.js +0 -36
- package/app-dist/routes/chunk-rgpbw2w0.js +0 -5
- package/app-dist/routes/chunk-rnpzv3d8.js +0 -2
- package/app-dist/routes/chunk-s5v8cv05.js +0 -2
- package/app-dist/routes/chunk-sbwn5bpc.js +0 -1
- package/app-dist/routes/chunk-sqbg8jbt.js +0 -33
- package/app-dist/routes/chunk-sv8dqnf7.js +0 -1
- package/app-dist/routes/chunk-t67sw3za.js +0 -1
- package/app-dist/routes/chunk-tjdpqwdf.js +0 -31
- package/app-dist/routes/chunk-tq2mfghg.js +0 -1
- package/app-dist/routes/chunk-ttn10vt6.js +0 -1
- package/app-dist/routes/chunk-v2hzpjxr.js +0 -1
- package/app-dist/routes/chunk-wfjjkw9y.js +0 -1
- package/app-dist/routes/chunk-wt8cxzmf.js +0 -31
- package/app-dist/routes/chunk-x45d372k.js +0 -5
- package/app-dist/routes/chunk-y3wsazkt.js +0 -1
- package/app-dist/routes/chunk-y7pmgc7t.js +0 -33
- package/app-dist/routes/chunk-zefdt2q3.js +0 -31
- package/app-dist/routes/dropdowns.js +0 -6
- package/app-dist/routes/home.js +0 -1
- package/app-dist/routes/icons.js +0 -1
- package/app-dist/routes/inputs.js +0 -12
- package/app-dist/routes/installation.js +0 -1
- package/app-dist/routes/layout.js +0 -1
- package/app-dist/routes/modals.js +0 -7
- package/app-dist/routes/navbar.js +0 -1
- package/app-dist/routes/progress.js +0 -1
- package/app-dist/routes/radios.js +0 -6
- package/app-dist/routes/switches.js +0 -6
- package/app-dist/routes/tabs.js +0 -1
- package/app-dist/routes/toasts.js +0 -16
- package/assets/fonts/material-symbols-mini.woff2 +0 -0
- package/assets/fonts/material-symbols.woff2 +0 -0
- package/assets/fonts/roboto-400.woff2 +0 -0
- package/assets/fonts/roboto-500.woff2 +0 -0
- package/assets/fonts/roboto-700.woff2 +0 -0
- package/assets/logo-banner-400.jpg +0 -0
- package/assets/logo-banner-400.webp +0 -0
- package/assets/logo-banner-800.webp +0 -0
- package/assets/logo-banner.jpg +0 -0
- package/assets/logo-icon-64.jpg +0 -0
- package/assets/logo-icon-64.webp +0 -0
- package/assets/logo-icon.jpg +0 -0
- package/assets/logo-square.jpg +0 -0
- package/bun.lock +0 -312
- package/bunfig.toml +0 -4
- package/custom-elements.json +0 -1916
- package/demo/api/sample-data.json +0 -38
- package/demo/content/alerts.html +0 -115
- package/demo/content/avatars.html +0 -70
- package/demo/content/badges.html +0 -65
- package/demo/content/buttons.html +0 -188
- package/demo/content/callouts.html +0 -91
- package/demo/content/cards.html +0 -121
- package/demo/content/checkboxes.html +0 -178
- package/demo/content/chips.html +0 -67
- package/demo/content/codeblocks.html +0 -101
- package/demo/content/confirms.html +0 -115
- package/demo/content/datatables.html +0 -149
- package/demo/content/dividers.html +0 -119
- package/demo/content/dropdowns.html +0 -89
- package/demo/content/enterprise.html +0 -252
- package/demo/content/home.html +0 -149
- package/demo/content/icons.html +0 -89
- package/demo/content/inputs.html +0 -135
- package/demo/content/installation.html +0 -16
- package/demo/content/layout.html +0 -136
- package/demo/content/modals.html +0 -141
- package/demo/content/navbar.html +0 -70
- package/demo/content/progress.html +0 -119
- package/demo/content/radios.html +0 -88
- package/demo/content/skeletons.html +0 -109
- package/demo/content/spinners.html +0 -96
- package/demo/content/switches.html +0 -84
- package/demo/content/tables.html +0 -124
- package/demo/content/tabs.html +0 -85
- package/demo/content/toasts.html +0 -116
- package/demo/content/tooltips.html +0 -107
- package/demo/content/virtual-lists.html +0 -233
- package/demo/favicon.ico +0 -0
- package/demo/favicon.png +0 -0
- package/demo/full.html +0 -52
- package/demo/iife.html +0 -46
- package/demo/manifest.json +0 -34
- package/demo/pages/datatable-demo.html +0 -237
- package/demo/pages/prompt-ui-demo.html +0 -218
- package/demo/pages/responsive-demo.html +0 -122
- package/demo/pages/schema-form-demo.html +0 -270
- package/demo/robots.txt +0 -6
- package/demo/shell.html +0 -712
- package/demo/sw.js +0 -387
- package/lighthouse-audit.mjs +0 -113
- package/scripts/analyze-components.js +0 -105
- package/scripts/build-app.js +0 -193
- package/scripts/build-framework.js +0 -444
- package/scripts/build-utils.js +0 -101
- package/scripts/test-isolated.js +0 -151
- package/server.js +0 -256
- package/tests/agents/agent-integration.test.js +0 -76
- package/tests/benchmark.html +0 -296
- package/tests/build/scan-components.test.js +0 -173
- package/tests/components/all-components.test.js +0 -245
- package/tests/components/all-missing-components.test.js +0 -574
- package/tests/components/mu-alert.test.js +0 -113
- package/tests/components/mu-avatar.test.js +0 -148
- package/tests/components/mu-badge.test.js +0 -92
- package/tests/components/mu-button.test.js +0 -112
- package/tests/components/mu-card.test.js +0 -89
- package/tests/components/mu-checkbox.test.js +0 -158
- package/tests/components/mu-chip.test.js +0 -118
- package/tests/components/mu-container.test.js +0 -120
- package/tests/components/mu-divider.test.js +0 -98
- package/tests/components/mu-drawer-item.test.js +0 -199
- package/tests/components/mu-drawer.test.js +0 -96
- package/tests/components/mu-dropdown.test.js +0 -125
- package/tests/components/mu-form.test.js +0 -138
- package/tests/components/mu-grid.test.js +0 -135
- package/tests/components/mu-icon.test.js +0 -110
- package/tests/components/mu-input.test.js +0 -131
- package/tests/components/mu-lazy.test.js +0 -103
- package/tests/components/mu-modal.test.js +0 -275
- package/tests/components/mu-navbar.test.js +0 -101
- package/tests/components/mu-progress.test.js +0 -115
- package/tests/components/mu-radio.test.js +0 -114
- package/tests/components/mu-repeat.test.js +0 -106
- package/tests/components/mu-sidebar.test.js +0 -126
- package/tests/components/mu-skeleton.test.js +0 -162
- package/tests/components/mu-stack.test.js +0 -143
- package/tests/components/mu-switch.test.js +0 -292
- package/tests/components/mu-table.test.js +0 -124
- package/tests/components/mu-tabs.test.js +0 -104
- package/tests/components/mu-textarea.test.js +0 -115
- package/tests/components/mu-toast.test.js +0 -321
- package/tests/components/mu-tooltip.test.js +0 -133
- package/tests/components/mu-virtual-list.test.js +0 -109
- package/tests/core/MuElement.test.js +0 -120
- package/tests/core/agent-api.test.js +0 -125
- package/tests/core/all-core-modules.test.js +0 -442
- package/tests/core/bus.test.js +0 -364
- package/tests/core/component-schema.test.js +0 -160
- package/tests/core/feature-registry.test.js +0 -198
- package/tests/core/form-state.test.js +0 -167
- package/tests/core/http.test.js +0 -119
- package/tests/core/keyboard.test.js +0 -319
- package/tests/core/layers.test.js +0 -129
- package/tests/core/namespaced-stores.test.js +0 -114
- package/tests/core/render.test.js +0 -121
- package/tests/core/ripple.test.js +0 -131
- package/tests/core/router.test.js +0 -89
- package/tests/core/scheduler.test.js +0 -121
- package/tests/core/signals.test.js +0 -128
- package/tests/core/store.test.js +0 -171
- package/tests/core/transitions.test.js +0 -82
- package/tests/e2e/accessibility-harness.html +0 -58
- package/tests/e2e/accessibility.test.js +0 -401
- package/tests/e2e/agent-features.test.js +0 -372
- package/tests/e2e/card-spacing.test.js +0 -287
- package/tests/e2e/components.test.js +0 -439
- package/tests/e2e/demo-routes.test.js +0 -478
- package/tests/e2e/layout-css-fallback.test.js +0 -334
- package/tests/e2e/mu-alert.e2e.test.js +0 -111
- package/tests/e2e/mu-checkbox.test.js +0 -489
- package/tests/e2e/mu-chip.test.js +0 -347
- package/tests/e2e/mu-form.test.js +0 -499
- package/tests/e2e/mu-icon.test.js +0 -114
- package/tests/e2e/mu-radio.test.js +0 -113
- package/tests/e2e/mu-skeleton.test.js +0 -140
- package/tests/e2e/mu-switch.test.js +0 -415
- package/tests/e2e/mu-tabs.test.js +0 -494
- package/tests/e2e/mu-textarea.test.js +0 -242
- package/tests/e2e/mu-virtual-list.test.js +0 -427
- package/tests/e2e/perf-memory.test.js +0 -161
- package/tests/e2e/puppeteer-helper.js +0 -137
- package/tests/e2e/puppeteer.test.js +0 -226
- package/tests/e2e/pwa.test.js +0 -261
- package/tests/e2e/test-harness.html +0 -319
- package/tests/manual/test-components.html +0 -120
- package/tests/memory-test.html +0 -309
- package/tests/setup-dom.js +0 -93
- package/tests/visual-test.html +0 -301
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Exhaustive Unit Tests for mu-chip Component
|
|
3
|
-
* Target: 13.98% → 90% 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 MuChip;
|
|
11
|
-
|
|
12
|
-
describe('mu-chip 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.CustomEvent = class CustomEvent extends Event {
|
|
25
|
-
constructor(type, options = {}) {
|
|
26
|
-
super(type, options);
|
|
27
|
-
this.detail = options.detail;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
|
|
31
|
-
globalThis.PointerEvent = class PointerEvent extends Event {
|
|
32
|
-
constructor(type, init = {}) { super(type, init); }
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const module = await import('../../src/components/mu-chip.js');
|
|
36
|
-
MuChip = module.MuChip;
|
|
37
|
-
|
|
38
|
-
MuChip.prototype.emit = function (eventName, detail) {
|
|
39
|
-
try { this.dispatchEvent(new Event(eventName, { bubbles: true })); } catch (e) { }
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
beforeEach(() => { body.innerHTML = ''; });
|
|
44
|
-
|
|
45
|
-
// REGISTRATION
|
|
46
|
-
test('should be registered', () => {
|
|
47
|
-
expect(customElements.get('mu-chip')).toBe(MuChip);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('should have correct baseClass', () => {
|
|
51
|
-
expect(MuChip.baseClass).toBe('mu-chip');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// DOM STRUCTURE
|
|
55
|
-
test('should render with base class', () => {
|
|
56
|
-
const el = document.createElement('mu-chip');
|
|
57
|
-
el.textContent = 'Tag';
|
|
58
|
-
body.appendChild(el);
|
|
59
|
-
expect(el.classList.contains('mu-chip')).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('should create label span', () => {
|
|
63
|
-
const el = document.createElement('mu-chip');
|
|
64
|
-
el.textContent = 'Filter';
|
|
65
|
-
body.appendChild(el);
|
|
66
|
-
expect(el.querySelector('.mu-chip__label')).not.toBeNull();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// SELECTION
|
|
70
|
-
test('should toggle selected on click', () => {
|
|
71
|
-
const el = document.createElement('mu-chip');
|
|
72
|
-
el.textContent = 'Tag';
|
|
73
|
-
body.appendChild(el);
|
|
74
|
-
expect(el.hasAttribute('selected')).toBe(false);
|
|
75
|
-
el.click();
|
|
76
|
-
expect(el.hasAttribute('selected')).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('should have selected class when selected', () => {
|
|
80
|
-
const el = document.createElement('mu-chip');
|
|
81
|
-
el.setAttribute('selected', '');
|
|
82
|
-
el.textContent = 'Tag';
|
|
83
|
-
body.appendChild(el);
|
|
84
|
-
expect(el.classList.contains('mu-chip--selected') || el.hasAttribute('selected')).toBe(true);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// VARIANTS
|
|
88
|
-
test('should support outlined variant', () => {
|
|
89
|
-
const el = document.createElement('mu-chip');
|
|
90
|
-
el.setAttribute('variant', 'outlined');
|
|
91
|
-
el.textContent = 'Outlined';
|
|
92
|
-
body.appendChild(el);
|
|
93
|
-
expect(el.getAttribute('variant')).toBe('outlined');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// REMOVABLE
|
|
97
|
-
test('should show remove button when removable', () => {
|
|
98
|
-
const el = document.createElement('mu-chip');
|
|
99
|
-
el.setAttribute('removable', '');
|
|
100
|
-
el.textContent = 'Removable';
|
|
101
|
-
body.appendChild(el);
|
|
102
|
-
const removeBtn = el.querySelector('.mu-chip__remove');
|
|
103
|
-
expect(removeBtn !== null || el.hasAttribute('removable')).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// DISPLAY
|
|
107
|
-
test('should have flex display', () => {
|
|
108
|
-
const el = document.createElement('mu-chip');
|
|
109
|
-
body.appendChild(el);
|
|
110
|
-
expect(['flex', 'inline-flex']).toContain(el.style.display);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('should have pointer cursor', () => {
|
|
114
|
-
const el = document.createElement('mu-chip');
|
|
115
|
-
body.appendChild(el);
|
|
116
|
-
expect(el.style.cursor).toBe('pointer');
|
|
117
|
-
});
|
|
118
|
-
});
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Unit Tests for mu-container Component
|
|
3
|
-
* Target: 97% → 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 MuContainer;
|
|
11
|
-
|
|
12
|
-
describe('mu-container 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-container.js');
|
|
27
|
-
MuContainer = module.MuContainer;
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
beforeEach(() => { body.innerHTML = ''; });
|
|
31
|
-
|
|
32
|
-
// REGISTRATION
|
|
33
|
-
test('should be registered', () => {
|
|
34
|
-
expect(customElements.get('mu-container')).toBe(MuContainer);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('should have correct baseClass', () => {
|
|
38
|
-
expect(MuContainer.baseClass).toBe('mu-container');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('should observe size, padding, center', () => {
|
|
42
|
-
expect(MuContainer.observedAttributes).toContain('size');
|
|
43
|
-
expect(MuContainer.observedAttributes).toContain('padding');
|
|
44
|
-
expect(MuContainer.observedAttributes).toContain('center');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// SIZE
|
|
48
|
-
test('should apply default lg size', () => {
|
|
49
|
-
const el = document.createElement('mu-container');
|
|
50
|
-
body.appendChild(el);
|
|
51
|
-
expect(el.style.maxWidth).toBe('1024px');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('should apply sm size', () => {
|
|
55
|
-
const el = document.createElement('mu-container');
|
|
56
|
-
el.setAttribute('size', 'sm');
|
|
57
|
-
body.appendChild(el);
|
|
58
|
-
expect(el.style.maxWidth).toBe('640px');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('should apply md size', () => {
|
|
62
|
-
const el = document.createElement('mu-container');
|
|
63
|
-
el.setAttribute('size', 'md');
|
|
64
|
-
body.appendChild(el);
|
|
65
|
-
expect(el.style.maxWidth).toBe('768px');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test('should apply xl size', () => {
|
|
69
|
-
const el = document.createElement('mu-container');
|
|
70
|
-
el.setAttribute('size', 'xl');
|
|
71
|
-
body.appendChild(el);
|
|
72
|
-
expect(el.style.maxWidth).toBe('1280px');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('should apply full size', () => {
|
|
76
|
-
const el = document.createElement('mu-container');
|
|
77
|
-
el.setAttribute('size', 'full');
|
|
78
|
-
body.appendChild(el);
|
|
79
|
-
expect(el.style.maxWidth).toBe('100%');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// PADDING
|
|
83
|
-
test('should apply default md padding', () => {
|
|
84
|
-
const el = document.createElement('mu-container');
|
|
85
|
-
body.appendChild(el);
|
|
86
|
-
expect(el.style.padding).toBe('16px');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('should apply sm padding', () => {
|
|
90
|
-
const el = document.createElement('mu-container');
|
|
91
|
-
el.setAttribute('padding', 'sm');
|
|
92
|
-
body.appendChild(el);
|
|
93
|
-
expect(el.style.padding).toBe('8px');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('should apply none padding', () => {
|
|
97
|
-
const el = document.createElement('mu-container');
|
|
98
|
-
el.setAttribute('padding', 'none');
|
|
99
|
-
body.appendChild(el);
|
|
100
|
-
expect(el.style.padding).toBe('0');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// CENTER
|
|
104
|
-
test('should center when center attr present', () => {
|
|
105
|
-
const el = document.createElement('mu-container');
|
|
106
|
-
el.setAttribute('center', '');
|
|
107
|
-
body.appendChild(el);
|
|
108
|
-
expect(el.style.marginLeft).toBe('auto');
|
|
109
|
-
expect(el.style.marginRight).toBe('auto');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// UPDATE
|
|
113
|
-
test('update should apply styles', () => {
|
|
114
|
-
const el = document.createElement('mu-container');
|
|
115
|
-
body.appendChild(el);
|
|
116
|
-
el.setAttribute('size', 'xl');
|
|
117
|
-
el.update('size', 'xl', 'lg');
|
|
118
|
-
expect(el.style.maxWidth).toBe('1280px');
|
|
119
|
-
});
|
|
120
|
-
});
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Unit Tests for mu-divider Component
|
|
3
|
-
* Target: 33% → 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 MuDivider;
|
|
11
|
-
|
|
12
|
-
describe('mu-divider 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-divider.js');
|
|
27
|
-
MuDivider = module.MuDivider;
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
beforeEach(() => { body.innerHTML = ''; });
|
|
31
|
-
|
|
32
|
-
// REGISTRATION
|
|
33
|
-
test('should be registered', () => {
|
|
34
|
-
expect(customElements.get('mu-divider')).toBe(MuDivider);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('should have correct baseClass', () => {
|
|
38
|
-
expect(MuDivider.baseClass).toBe('mu-divider');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('should observe vertical and inset', () => {
|
|
42
|
-
expect(MuDivider.observedAttributes).toContain('vertical');
|
|
43
|
-
expect(MuDivider.observedAttributes).toContain('inset');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// HORIZONTAL (default)
|
|
47
|
-
test('should set height 1px for horizontal', () => {
|
|
48
|
-
const el = document.createElement('mu-divider');
|
|
49
|
-
body.appendChild(el);
|
|
50
|
-
expect(el.style.height).toBe('1px');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('should set width 100% for horizontal', () => {
|
|
54
|
-
const el = document.createElement('mu-divider');
|
|
55
|
-
body.appendChild(el);
|
|
56
|
-
expect(el.style.width).toBe('100%');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// VERTICAL
|
|
60
|
-
test('should set width 1px for vertical', () => {
|
|
61
|
-
const el = document.createElement('mu-divider');
|
|
62
|
-
el.setAttribute('vertical', '');
|
|
63
|
-
body.appendChild(el);
|
|
64
|
-
expect(el.style.width).toBe('1px');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('should set minHeight for vertical', () => {
|
|
68
|
-
const el = document.createElement('mu-divider');
|
|
69
|
-
el.setAttribute('vertical', '');
|
|
70
|
-
body.appendChild(el);
|
|
71
|
-
expect(el.style.minHeight).toBe('24px');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// INSET
|
|
75
|
-
test('should apply inset margin for horizontal', () => {
|
|
76
|
-
const el = document.createElement('mu-divider');
|
|
77
|
-
el.setAttribute('inset', '');
|
|
78
|
-
body.appendChild(el);
|
|
79
|
-
expect(el.style.margin).toBe('0 16px');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('should apply inset margin for vertical', () => {
|
|
83
|
-
const el = document.createElement('mu-divider');
|
|
84
|
-
el.setAttribute('vertical', '');
|
|
85
|
-
el.setAttribute('inset', '');
|
|
86
|
-
body.appendChild(el);
|
|
87
|
-
expect(el.style.margin).toBe('0 8px');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// UPDATE
|
|
91
|
-
test('update should re-render', () => {
|
|
92
|
-
const el = document.createElement('mu-divider');
|
|
93
|
-
body.appendChild(el);
|
|
94
|
-
el.setAttribute('vertical', '');
|
|
95
|
-
el.update('vertical', '', null);
|
|
96
|
-
expect(el.style.width).toBe('1px');
|
|
97
|
-
});
|
|
98
|
-
});
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Unit Tests for mu-drawer-item Component
|
|
3
|
-
* Focus: Accessibility requirements (aria-label, label capture)
|
|
4
|
-
*
|
|
5
|
-
* These tests ensure:
|
|
6
|
-
* 1. aria-label is ALWAYS present on the rendered link
|
|
7
|
-
* 2. Label is captured synchronously before DOM manipulation
|
|
8
|
-
* 3. Text content fallback works for inline labels
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
|
|
12
|
-
import { parseHTML } from 'linkedom';
|
|
13
|
-
|
|
14
|
-
let document, customElements, body;
|
|
15
|
-
let MuDrawerItem, MuNavItem;
|
|
16
|
-
|
|
17
|
-
describe('mu-drawer-item Accessibility Tests', () => {
|
|
18
|
-
|
|
19
|
-
beforeAll(async () => {
|
|
20
|
-
const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
|
|
21
|
-
document = dom.document;
|
|
22
|
-
customElements = dom.customElements;
|
|
23
|
-
body = document.body;
|
|
24
|
-
|
|
25
|
-
globalThis.window = dom.window;
|
|
26
|
-
globalThis.document = document;
|
|
27
|
-
globalThis.customElements = customElements;
|
|
28
|
-
globalThis.HTMLElement = dom.HTMLElement;
|
|
29
|
-
globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
|
|
30
|
-
globalThis.getComputedStyle = () => ({ position: 'relative' });
|
|
31
|
-
|
|
32
|
-
const module = await import('../../src/components/mu-drawer-item.js');
|
|
33
|
-
MuDrawerItem = module.MuDrawerItem;
|
|
34
|
-
MuNavItem = module.MuNavItem;
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
beforeEach(() => { body.innerHTML = ''; });
|
|
38
|
-
|
|
39
|
-
// REGISTRATION
|
|
40
|
-
test('should be registered as mu-drawer-item', () => {
|
|
41
|
-
expect(customElements.get('mu-drawer-item')).toBe(MuDrawerItem);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('should be registered as mu-nav-item alias', () => {
|
|
45
|
-
expect(customElements.get('mu-nav-item')).toBeDefined();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// ARIA-LABEL - CRITICAL ACCESSIBILITY FIX
|
|
49
|
-
describe('aria-label accessibility', () => {
|
|
50
|
-
|
|
51
|
-
test('should include aria-label when label attribute is set', () => {
|
|
52
|
-
const el = document.createElement('mu-drawer-item');
|
|
53
|
-
el.setAttribute('label', 'Home');
|
|
54
|
-
el.setAttribute('href', '#home');
|
|
55
|
-
el.setAttribute('icon', 'home');
|
|
56
|
-
body.appendChild(el);
|
|
57
|
-
|
|
58
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
59
|
-
expect(link).toBeTruthy();
|
|
60
|
-
expect(link.getAttribute('aria-label')).toBe('Home');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('should include aria-label when text content is provided inline', () => {
|
|
64
|
-
// This simulates: <mu-drawer-item>Dashboard</mu-drawer-item>
|
|
65
|
-
const el = document.createElement('mu-drawer-item');
|
|
66
|
-
el.textContent = 'Dashboard';
|
|
67
|
-
el.setAttribute('href', '#dashboard');
|
|
68
|
-
el.setAttribute('icon', 'dashboard');
|
|
69
|
-
body.appendChild(el);
|
|
70
|
-
|
|
71
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
72
|
-
expect(link).toBeTruthy();
|
|
73
|
-
expect(link.getAttribute('aria-label')).toBe('Dashboard');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('should mark visible label as aria-hidden to avoid duplication', () => {
|
|
77
|
-
const el = document.createElement('mu-drawer-item');
|
|
78
|
-
el.setAttribute('label', 'Settings');
|
|
79
|
-
el.setAttribute('href', '#settings');
|
|
80
|
-
el.setAttribute('icon', 'settings');
|
|
81
|
-
body.appendChild(el);
|
|
82
|
-
|
|
83
|
-
const labelSpan = el.querySelector('.mu-drawer-item-label');
|
|
84
|
-
expect(labelSpan).toBeTruthy();
|
|
85
|
-
expect(labelSpan.getAttribute('aria-hidden')).toBe('true');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('should NOT have empty aria-label', () => {
|
|
89
|
-
const el = document.createElement('mu-drawer-item');
|
|
90
|
-
el.setAttribute('label', 'Profile');
|
|
91
|
-
el.setAttribute('href', '#profile');
|
|
92
|
-
body.appendChild(el);
|
|
93
|
-
|
|
94
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
95
|
-
const ariaLabel = link.getAttribute('aria-label');
|
|
96
|
-
expect(ariaLabel).toBeTruthy();
|
|
97
|
-
expect(ariaLabel.length).toBeGreaterThan(0);
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// LABEL CAPTURE TIMING - REGRESSION FIX
|
|
102
|
-
describe('label capture timing', () => {
|
|
103
|
-
|
|
104
|
-
test('should capture text content in connectedCallback', () => {
|
|
105
|
-
const el = document.createElement('mu-drawer-item');
|
|
106
|
-
el.textContent = 'Navigation';
|
|
107
|
-
el.setAttribute('href', '#nav');
|
|
108
|
-
body.appendChild(el);
|
|
109
|
-
|
|
110
|
-
// After connecting, label should be captured and used
|
|
111
|
-
expect(el.label).toBe('Navigation');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test('should preserve label attribute over text content', () => {
|
|
115
|
-
const el = document.createElement('mu-drawer-item');
|
|
116
|
-
el.setAttribute('label', 'Explicit Label');
|
|
117
|
-
el.textContent = 'Fallback Text';
|
|
118
|
-
el.setAttribute('href', '#test');
|
|
119
|
-
body.appendChild(el);
|
|
120
|
-
|
|
121
|
-
expect(el.label).toBe('Explicit Label');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test('should use captured text when label attribute absent', () => {
|
|
125
|
-
const el = document.createElement('mu-drawer-item');
|
|
126
|
-
el.appendChild(document.createTextNode('Captured'));
|
|
127
|
-
el.setAttribute('href', '#captured');
|
|
128
|
-
body.appendChild(el);
|
|
129
|
-
|
|
130
|
-
expect(el.label).toBe('Captured');
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// MU-NAV-ITEM (Bottom Navigation)
|
|
135
|
-
describe('mu-nav-item accessibility', () => {
|
|
136
|
-
|
|
137
|
-
test('should set vertical layout by default', () => {
|
|
138
|
-
const el = document.createElement('mu-nav-item');
|
|
139
|
-
el.setAttribute('label', 'Home');
|
|
140
|
-
el.setAttribute('icon', 'home');
|
|
141
|
-
body.appendChild(el);
|
|
142
|
-
|
|
143
|
-
expect(el.getAttribute('layout')).toBe('vertical');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('should include aria-label on bottom nav items', () => {
|
|
147
|
-
const el = document.createElement('mu-nav-item');
|
|
148
|
-
el.setAttribute('label', 'Search');
|
|
149
|
-
el.setAttribute('href', '#search');
|
|
150
|
-
el.setAttribute('icon', 'search');
|
|
151
|
-
body.appendChild(el);
|
|
152
|
-
|
|
153
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
154
|
-
expect(link).toBeTruthy();
|
|
155
|
-
expect(link.getAttribute('aria-label')).toBe('Search');
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test('should use label attribute for bottom nav items (recommended pattern)', () => {
|
|
159
|
-
// Note: For mu-nav-item, always use label attribute instead of text content
|
|
160
|
-
// because the layout attribute setting can trigger early render
|
|
161
|
-
const el = document.createElement('mu-nav-item');
|
|
162
|
-
el.setAttribute('label', 'Favorites');
|
|
163
|
-
el.setAttribute('href', '#favorites');
|
|
164
|
-
el.setAttribute('icon', 'star');
|
|
165
|
-
body.appendChild(el);
|
|
166
|
-
|
|
167
|
-
expect(el.label).toBe('Favorites');
|
|
168
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
169
|
-
expect(link.getAttribute('aria-label')).toBe('Favorites');
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// DISABLED STATE ACCESSIBILITY
|
|
174
|
-
describe('disabled state accessibility', () => {
|
|
175
|
-
|
|
176
|
-
test('should set aria-disabled on disabled links', () => {
|
|
177
|
-
const el = document.createElement('mu-drawer-item');
|
|
178
|
-
el.setAttribute('label', 'Locked');
|
|
179
|
-
el.setAttribute('href', '#locked');
|
|
180
|
-
el.setAttribute('disabled', '');
|
|
181
|
-
body.appendChild(el);
|
|
182
|
-
|
|
183
|
-
const link = el.querySelector('a.mu-drawer-item-link');
|
|
184
|
-
expect(link.getAttribute('aria-disabled')).toBe('true');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test('should set disabled attribute on buttons', () => {
|
|
188
|
-
const el = document.createElement('mu-drawer-item');
|
|
189
|
-
el.setAttribute('label', 'Action');
|
|
190
|
-
// No href = renders as button
|
|
191
|
-
el.setAttribute('disabled', '');
|
|
192
|
-
body.appendChild(el);
|
|
193
|
-
|
|
194
|
-
const button = el.querySelector('button.mu-drawer-item-link');
|
|
195
|
-
expect(button).toBeTruthy();
|
|
196
|
-
expect(button.hasAttribute('disabled')).toBe(true);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Unit Tests for mu-drawer Component
|
|
3
|
-
* Focus: ARIA accessibility structure (aria-required-parent compliance)
|
|
4
|
-
*
|
|
5
|
-
* These tests ensure:
|
|
6
|
-
* 1. The drawer content container has role="menu"
|
|
7
|
-
* 2. menuitem children have a proper menu parent (aria-required-parent)
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, test, expect, beforeAll, beforeEach } from 'bun:test';
|
|
11
|
-
import { parseHTML } from 'linkedom';
|
|
12
|
-
|
|
13
|
-
let document, customElements, body;
|
|
14
|
-
|
|
15
|
-
describe('mu-drawer ARIA Accessibility Tests', () => {
|
|
16
|
-
|
|
17
|
-
beforeAll(async () => {
|
|
18
|
-
const dom = parseHTML('<!DOCTYPE html><html><body></body></html>');
|
|
19
|
-
document = dom.document;
|
|
20
|
-
customElements = dom.customElements;
|
|
21
|
-
body = document.body;
|
|
22
|
-
|
|
23
|
-
globalThis.window = dom.window;
|
|
24
|
-
globalThis.document = document;
|
|
25
|
-
globalThis.customElements = customElements;
|
|
26
|
-
globalThis.HTMLElement = dom.HTMLElement;
|
|
27
|
-
globalThis.requestAnimationFrame = (cb) => { cb(Date.now()); return 0; };
|
|
28
|
-
globalThis.getComputedStyle = () => ({ position: 'relative' });
|
|
29
|
-
// Mock matchMedia for breakpoints
|
|
30
|
-
globalThis.matchMedia = () => ({ matches: false, addEventListener: () => { }, removeEventListener: () => { } });
|
|
31
|
-
|
|
32
|
-
// Import components
|
|
33
|
-
await import('../../src/components/mu-drawer.js');
|
|
34
|
-
await import('../../src/components/mu-drawer-item.js');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
beforeEach(() => { body.innerHTML = ''; });
|
|
38
|
-
|
|
39
|
-
test('should render with role="navigation" on nav element', () => {
|
|
40
|
-
const el = document.createElement('mu-drawer');
|
|
41
|
-
body.appendChild(el);
|
|
42
|
-
|
|
43
|
-
const nav = el.querySelector('.mu-drawer-nav');
|
|
44
|
-
expect(nav).toBeTruthy();
|
|
45
|
-
expect(nav.getAttribute('role')).toBe('navigation');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('should have role="menu" on content container (aria-required-parent fix)', () => {
|
|
49
|
-
const el = document.createElement('mu-drawer');
|
|
50
|
-
body.appendChild(el);
|
|
51
|
-
|
|
52
|
-
const content = el.querySelector('.mu-drawer-content');
|
|
53
|
-
expect(content).toBeTruthy();
|
|
54
|
-
expect(content.getAttribute('role')).toBe('menu');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('menuitem children are inside menu parent (Lighthouse aria-required-parent)', () => {
|
|
58
|
-
// Create drawer with items
|
|
59
|
-
const el = document.createElement('mu-drawer');
|
|
60
|
-
const item1 = document.createElement('mu-drawer-item');
|
|
61
|
-
item1.setAttribute('label', 'Home');
|
|
62
|
-
item1.setAttribute('icon', 'home');
|
|
63
|
-
const item2 = document.createElement('mu-drawer-item');
|
|
64
|
-
item2.setAttribute('label', 'Settings');
|
|
65
|
-
item2.setAttribute('icon', 'settings');
|
|
66
|
-
|
|
67
|
-
el.appendChild(item1);
|
|
68
|
-
el.appendChild(item2);
|
|
69
|
-
body.appendChild(el);
|
|
70
|
-
|
|
71
|
-
// After render, items should be inside a role="menu" parent
|
|
72
|
-
const items = el.querySelectorAll('mu-drawer-item');
|
|
73
|
-
expect(items.length).toBeGreaterThan(0);
|
|
74
|
-
|
|
75
|
-
items.forEach(item => {
|
|
76
|
-
// Each item should have role="menuitem"
|
|
77
|
-
expect(item.getAttribute('role')).toBe('menuitem');
|
|
78
|
-
// And should be inside a role="menu" parent
|
|
79
|
-
const menuParent = item.closest('[role="menu"]');
|
|
80
|
-
expect(menuParent).toBeTruthy();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('should maintain correct ARIA structure on mode changes', () => {
|
|
85
|
-
const el = document.createElement('mu-drawer');
|
|
86
|
-
el.setAttribute('mode', 'permanent');
|
|
87
|
-
body.appendChild(el);
|
|
88
|
-
|
|
89
|
-
// Structure should be: nav[role="navigation"] > div.content[role="menu"] > items[role="menuitem"]
|
|
90
|
-
const nav = el.querySelector('.mu-drawer-nav');
|
|
91
|
-
expect(nav.getAttribute('role')).toBe('navigation');
|
|
92
|
-
|
|
93
|
-
const content = el.querySelector('.mu-drawer-content');
|
|
94
|
-
expect(content.getAttribute('role')).toBe('menu');
|
|
95
|
-
});
|
|
96
|
-
});
|