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,494 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Comprehensive Unit Tests for mu-tabs Component
|
|
3
|
-
*
|
|
4
|
-
* Tests:
|
|
5
|
-
* - Component registration and basic rendering
|
|
6
|
-
* - Tab click handling and active state switching
|
|
7
|
-
* - Event emission (mu-tab-change)
|
|
8
|
-
* - Indicator positioning
|
|
9
|
-
* - Accessibility attributes
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { describe, test, expect, beforeAll, afterEach, afterAll } from 'bun:test';
|
|
13
|
-
import { launchBrowser, puppeteer } from './puppeteer-helper.js';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
|
-
import { dirname, join } from 'path'
|
|
16
|
-
|
|
17
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
const __dirname = dirname(__filename);
|
|
19
|
-
|
|
20
|
-
// Helper to wait
|
|
21
|
-
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
22
|
-
|
|
23
|
-
describe('mu-tabs Component E2E Tests', () => {
|
|
24
|
-
let browser;
|
|
25
|
-
let page;
|
|
26
|
-
let server;
|
|
27
|
-
|
|
28
|
-
beforeAll(async () => {
|
|
29
|
-
const projectRoot = join(__dirname, '../..');
|
|
30
|
-
|
|
31
|
-
// Start HTTP server
|
|
32
|
-
server = Bun.serve({
|
|
33
|
-
port: 0,
|
|
34
|
-
async fetch(req) {
|
|
35
|
-
const url = new URL(req.url);
|
|
36
|
-
let filePath = join(projectRoot, url.pathname);
|
|
37
|
-
|
|
38
|
-
if (url.pathname === '/') {
|
|
39
|
-
filePath = join(projectRoot, 'demo/shell.html');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const file = Bun.file(filePath);
|
|
44
|
-
const exists = await file.exists();
|
|
45
|
-
if (!exists) {
|
|
46
|
-
return new Response('Not Found', { status: 404 });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const content = await file.arrayBuffer();
|
|
50
|
-
const ext = filePath.split('.').pop();
|
|
51
|
-
const mimeTypes = {
|
|
52
|
-
'html': 'text/html',
|
|
53
|
-
'js': 'text/javascript',
|
|
54
|
-
'css': 'text/css',
|
|
55
|
-
'json': 'application/json',
|
|
56
|
-
'svg': 'image/svg+xml'
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return new Response(content, {
|
|
60
|
-
headers: { 'Content-Type': mimeTypes[ext] || 'application/octet-stream' }
|
|
61
|
-
});
|
|
62
|
-
} catch (e) {
|
|
63
|
-
return new Response('Error: ' + e.message, { status: 500 });
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
console.log(`[mu-tabs test] Server started at http://localhost:${server.port}`);
|
|
69
|
-
|
|
70
|
-
browser = await puppeteer.launch({
|
|
71
|
-
headless: true,
|
|
72
|
-
executablePath: '/tmp/puppeteer/chrome-headless-shell/mac_arm-144.0.7559.96/chrome-headless-shell-mac-arm64/chrome-headless-shell',
|
|
73
|
-
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
74
|
-
userDataDir: `./.tmp/puppeteer-mu_tabs-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
75
|
-
});
|
|
76
|
-
page = await browser.newPage();
|
|
77
|
-
}, 60000);
|
|
78
|
-
|
|
79
|
-
afterEach(async () => {
|
|
80
|
-
// Navigate to blank page to reset state between tests
|
|
81
|
-
await page.goto('about:blank');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
afterAll(async () => {
|
|
85
|
-
if (browser) await browser.close();
|
|
86
|
-
if (server) server.stop();
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// ========================================
|
|
90
|
-
// COMPONENT REGISTRATION
|
|
91
|
-
// ========================================
|
|
92
|
-
|
|
93
|
-
test('mu-tabs should be registered as custom element', async () => {
|
|
94
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
95
|
-
waitUntil: 'networkidle0'
|
|
96
|
-
});
|
|
97
|
-
await delay(500);
|
|
98
|
-
|
|
99
|
-
const isRegistered = await page.evaluate(() => {
|
|
100
|
-
return customElements.get('mu-tabs') !== undefined;
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
expect(isRegistered).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('mu-tab should be registered as custom element', async () => {
|
|
107
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
108
|
-
waitUntil: 'networkidle0'
|
|
109
|
-
});
|
|
110
|
-
await delay(500);
|
|
111
|
-
|
|
112
|
-
const isRegistered = await page.evaluate(() => {
|
|
113
|
-
return customElements.get('mu-tab') !== undefined;
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
expect(isRegistered).toBe(true);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// ========================================
|
|
120
|
-
// BASIC RENDERING
|
|
121
|
-
// ========================================
|
|
122
|
-
|
|
123
|
-
test('mu-tabs should render with base class', async () => {
|
|
124
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
125
|
-
waitUntil: 'networkidle0'
|
|
126
|
-
});
|
|
127
|
-
await delay(500);
|
|
128
|
-
|
|
129
|
-
const hasBaseClass = await page.evaluate(() => {
|
|
130
|
-
const tabs = document.querySelector('mu-tabs');
|
|
131
|
-
return tabs ? tabs.classList.contains('mu-tabs') : false;
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
expect(hasBaseClass).toBe(true);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test('mu-tabs should create tabs list wrapper', async () => {
|
|
138
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
139
|
-
waitUntil: 'networkidle0'
|
|
140
|
-
});
|
|
141
|
-
await delay(500);
|
|
142
|
-
|
|
143
|
-
const hasList = await page.evaluate(() => {
|
|
144
|
-
const tabs = document.querySelector('mu-tabs');
|
|
145
|
-
return tabs ? tabs.querySelector('.mu-tabs__list') !== null : false;
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
expect(hasList).toBe(true);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// ========================================
|
|
152
|
-
// ACCESSIBILITY
|
|
153
|
-
// ========================================
|
|
154
|
-
|
|
155
|
-
test('mu-tabs list should have role=tablist', async () => {
|
|
156
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
157
|
-
waitUntil: 'networkidle0'
|
|
158
|
-
});
|
|
159
|
-
await delay(500);
|
|
160
|
-
|
|
161
|
-
const hasRole = await page.evaluate(() => {
|
|
162
|
-
const tabs = document.querySelector('mu-tabs');
|
|
163
|
-
if (!tabs) return false;
|
|
164
|
-
const list = tabs.querySelector('.mu-tabs__list');
|
|
165
|
-
return list ? list.getAttribute('role') === 'tablist' : false;
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
expect(hasRole).toBe(true);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test('mu-tab should have role=tab', async () => {
|
|
172
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
173
|
-
waitUntil: 'networkidle0'
|
|
174
|
-
});
|
|
175
|
-
await delay(500);
|
|
176
|
-
|
|
177
|
-
const hasRole = await page.evaluate(() => {
|
|
178
|
-
const tab = document.querySelector('mu-tab');
|
|
179
|
-
return tab ? tab.getAttribute('role') === 'tab' : false;
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(hasRole).toBe(true);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test('active tab should have aria-selected=true', async () => {
|
|
186
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
187
|
-
waitUntil: 'networkidle0'
|
|
188
|
-
});
|
|
189
|
-
await delay(500);
|
|
190
|
-
|
|
191
|
-
const ariaSelected = await page.evaluate(() => {
|
|
192
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
193
|
-
if (tabs.length === 0) return null;
|
|
194
|
-
// First tab should be active by default
|
|
195
|
-
return tabs[0].getAttribute('aria-selected');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
expect(ariaSelected).toBe('true');
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('inactive tabs should have aria-selected=false', async () => {
|
|
202
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
203
|
-
waitUntil: 'networkidle0'
|
|
204
|
-
});
|
|
205
|
-
await delay(500);
|
|
206
|
-
|
|
207
|
-
const ariaSelected = await page.evaluate(() => {
|
|
208
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
209
|
-
if (tabs.length < 2) return null;
|
|
210
|
-
// Second tab should be inactive by default
|
|
211
|
-
return tabs[1].getAttribute('aria-selected');
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
expect(ariaSelected).toBe('false');
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// ========================================
|
|
218
|
-
// TAB SWITCHING
|
|
219
|
-
// ========================================
|
|
220
|
-
|
|
221
|
-
test('clicking a tab should update active attribute', async () => {
|
|
222
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
223
|
-
waitUntil: 'networkidle0'
|
|
224
|
-
});
|
|
225
|
-
await delay(500);
|
|
226
|
-
|
|
227
|
-
const result = await page.evaluate(() => {
|
|
228
|
-
const tabsContainer = document.querySelector('mu-tabs');
|
|
229
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
230
|
-
if (!tabsContainer || tabs.length < 2) {
|
|
231
|
-
return { before: null, after: null, clicked: false };
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const before = tabsContainer.getAttribute('active');
|
|
235
|
-
tabs[1].click();
|
|
236
|
-
const after = tabsContainer.getAttribute('active');
|
|
237
|
-
|
|
238
|
-
return { before, after, clicked: true };
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
expect(result.clicked).toBe(true);
|
|
242
|
-
expect(result.before).toBe('0');
|
|
243
|
-
expect(result.after).toBe('1');
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test('clicking a tab should add is-active class to that tab', async () => {
|
|
247
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
248
|
-
waitUntil: 'networkidle0'
|
|
249
|
-
});
|
|
250
|
-
await delay(500);
|
|
251
|
-
|
|
252
|
-
const result = await page.evaluate(() => {
|
|
253
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
254
|
-
if (tabs.length < 2) return { tab1Active: false, tab2Active: false };
|
|
255
|
-
|
|
256
|
-
// Click second tab
|
|
257
|
-
tabs[1].click();
|
|
258
|
-
|
|
259
|
-
return {
|
|
260
|
-
tab1Active: tabs[0].classList.contains('is-active'),
|
|
261
|
-
tab2Active: tabs[1].classList.contains('is-active')
|
|
262
|
-
};
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
expect(result.tab1Active).toBe(false);
|
|
266
|
-
expect(result.tab2Active).toBe(true);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test('clicking a tab should update aria-selected on all tabs', async () => {
|
|
270
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
271
|
-
waitUntil: 'networkidle0'
|
|
272
|
-
});
|
|
273
|
-
await delay(500);
|
|
274
|
-
|
|
275
|
-
const result = await page.evaluate(() => {
|
|
276
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
277
|
-
if (tabs.length < 2) return null;
|
|
278
|
-
|
|
279
|
-
// Click second tab
|
|
280
|
-
tabs[1].click();
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
tab1AriaSelected: tabs[0].getAttribute('aria-selected'),
|
|
284
|
-
tab2AriaSelected: tabs[1].getAttribute('aria-selected')
|
|
285
|
-
};
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
expect(result.tab1AriaSelected).toBe('false');
|
|
289
|
-
expect(result.tab2AriaSelected).toBe('true');
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// ========================================
|
|
293
|
-
// EVENT EMISSION
|
|
294
|
-
// ========================================
|
|
295
|
-
|
|
296
|
-
test('clicking a tab should emit mu-tab-change event', async () => {
|
|
297
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
298
|
-
waitUntil: 'networkidle0'
|
|
299
|
-
});
|
|
300
|
-
await delay(500);
|
|
301
|
-
|
|
302
|
-
const eventFired = await page.evaluate(() => {
|
|
303
|
-
return new Promise(resolve => {
|
|
304
|
-
const tabsContainer = document.querySelector('mu-tabs');
|
|
305
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
306
|
-
if (!tabsContainer || tabs.length < 2) {
|
|
307
|
-
resolve({ fired: false, reason: 'No tabs found' });
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
let eventData = null;
|
|
312
|
-
tabsContainer.addEventListener('mu-tab-change', (e) => {
|
|
313
|
-
eventData = e.detail;
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
tabs[1].click();
|
|
317
|
-
|
|
318
|
-
// Check immediately
|
|
319
|
-
setTimeout(() => {
|
|
320
|
-
resolve({ fired: eventData !== null, index: eventData?.index });
|
|
321
|
-
}, 100);
|
|
322
|
-
});
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
expect(eventFired.fired).toBe(true);
|
|
326
|
-
expect(eventFired.index).toBe(1);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
test('mu-tab-change event should have correct index in detail', async () => {
|
|
330
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
331
|
-
waitUntil: 'networkidle0'
|
|
332
|
-
});
|
|
333
|
-
await delay(500);
|
|
334
|
-
|
|
335
|
-
const result = await page.evaluate(() => {
|
|
336
|
-
return new Promise(resolve => {
|
|
337
|
-
const tabsContainer = document.querySelector('mu-tabs');
|
|
338
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
339
|
-
if (!tabsContainer || tabs.length < 3) {
|
|
340
|
-
resolve({ success: false });
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
const indices = [];
|
|
345
|
-
tabsContainer.addEventListener('mu-tab-change', (e) => {
|
|
346
|
-
indices.push(e.detail.index);
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
// Click each tab
|
|
350
|
-
tabs[0].click();
|
|
351
|
-
tabs[1].click();
|
|
352
|
-
tabs[2].click();
|
|
353
|
-
|
|
354
|
-
setTimeout(() => {
|
|
355
|
-
resolve({ success: true, indices });
|
|
356
|
-
}, 100);
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
expect(result.success).toBe(true);
|
|
361
|
-
// Note: First click might not emit if already active
|
|
362
|
-
expect(result.indices).toContain(1);
|
|
363
|
-
expect(result.indices).toContain(2);
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
// ========================================
|
|
367
|
-
// INDICATOR POSITIONING
|
|
368
|
-
// ========================================
|
|
369
|
-
|
|
370
|
-
test('indicator should update position on tab switch', async () => {
|
|
371
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#tabs`, {
|
|
372
|
-
waitUntil: 'networkidle0'
|
|
373
|
-
});
|
|
374
|
-
await delay(500);
|
|
375
|
-
|
|
376
|
-
const result = await page.evaluate(() => {
|
|
377
|
-
const tabsContainer = document.querySelector('mu-tabs');
|
|
378
|
-
const tabs = document.querySelectorAll('mu-tab');
|
|
379
|
-
const list = tabsContainer?.querySelector('.mu-tabs__list');
|
|
380
|
-
if (!list || tabs.length < 2) return null;
|
|
381
|
-
|
|
382
|
-
const beforeLeft = list.style.getPropertyValue('--indicator-left');
|
|
383
|
-
tabs[1].click();
|
|
384
|
-
const afterLeft = list.style.getPropertyValue('--indicator-left');
|
|
385
|
-
|
|
386
|
-
return { beforeLeft, afterLeft };
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
expect(result).not.toBeNull();
|
|
390
|
-
expect(result.beforeLeft).not.toBe(result.afterLeft);
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// ========================================
|
|
394
|
-
// ENTERPRISE DEMO TABS
|
|
395
|
-
// ========================================
|
|
396
|
-
|
|
397
|
-
test('Enterprise section tabs should work correctly', async () => {
|
|
398
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#enterprise`, {
|
|
399
|
-
waitUntil: 'networkidle0'
|
|
400
|
-
});
|
|
401
|
-
await delay(1000);
|
|
402
|
-
|
|
403
|
-
const result = await page.evaluate(() => {
|
|
404
|
-
const tabsContainer = document.getElementById('enterprise-doc-tabs');
|
|
405
|
-
if (!tabsContainer) return { found: false, issue: 'enterprise-doc-tabs not found' };
|
|
406
|
-
|
|
407
|
-
const tabs = tabsContainer.querySelectorAll('mu-tab');
|
|
408
|
-
if (tabs.length < 3) return { found: false, issue: `Only ${tabs.length} tabs found` };
|
|
409
|
-
|
|
410
|
-
// Store initial state
|
|
411
|
-
const initialActive = tabsContainer.getAttribute('active');
|
|
412
|
-
|
|
413
|
-
let eventFired = false;
|
|
414
|
-
let eventIndex = null;
|
|
415
|
-
|
|
416
|
-
tabsContainer.addEventListener('mu-tab-change', (e) => {
|
|
417
|
-
eventFired = true;
|
|
418
|
-
eventIndex = e.detail.index;
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// Click EXAMPLES tab (index 2)
|
|
422
|
-
tabs[2].click();
|
|
423
|
-
|
|
424
|
-
const afterActive = tabsContainer.getAttribute('active');
|
|
425
|
-
|
|
426
|
-
return {
|
|
427
|
-
found: true,
|
|
428
|
-
tabCount: tabs.length,
|
|
429
|
-
initialActive,
|
|
430
|
-
afterActive,
|
|
431
|
-
eventFired,
|
|
432
|
-
eventIndex,
|
|
433
|
-
tab2HasIsActive: tabs[2].classList.contains('is-active')
|
|
434
|
-
};
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
expect(result.found).toBe(true);
|
|
438
|
-
expect(result.tabCount).toBe(3);
|
|
439
|
-
expect(result.afterActive).toBe('2');
|
|
440
|
-
expect(result.eventFired).toBe(true);
|
|
441
|
-
expect(result.eventIndex).toBe(2);
|
|
442
|
-
expect(result.tab2HasIsActive).toBe(true);
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
test('Enterprise section tab content should switch when tabs are clicked', async () => {
|
|
446
|
-
await page.goto(`http://localhost:${server.port}/demo/shell.html#enterprise`, {
|
|
447
|
-
waitUntil: 'networkidle0'
|
|
448
|
-
});
|
|
449
|
-
await delay(1000);
|
|
450
|
-
|
|
451
|
-
const result = await page.evaluate(() => {
|
|
452
|
-
const tabsContainer = document.getElementById('enterprise-doc-tabs');
|
|
453
|
-
const overview = document.getElementById('enterprise-overview');
|
|
454
|
-
const api = document.getElementById('enterprise-api');
|
|
455
|
-
const examples = document.getElementById('enterprise-examples');
|
|
456
|
-
|
|
457
|
-
if (!tabsContainer || !overview || !api || !examples) {
|
|
458
|
-
return { success: false, issue: 'Elements not found' };
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Setup listener to switch content (simulate setupDocTabs)
|
|
462
|
-
tabsContainer.addEventListener('mu-tab-change', (e) => {
|
|
463
|
-
const index = e.detail.index;
|
|
464
|
-
overview.style.display = index === 0 ? 'block' : 'none';
|
|
465
|
-
api.style.display = index === 1 ? 'block' : 'none';
|
|
466
|
-
examples.style.display = index === 2 ? 'block' : 'none';
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// Initial state
|
|
470
|
-
const initialOverview = overview.style.display !== 'none';
|
|
471
|
-
const initialExamples = examples.style.display !== 'none';
|
|
472
|
-
|
|
473
|
-
// Click EXAMPLES tab
|
|
474
|
-
const tabs = tabsContainer.querySelectorAll('mu-tab');
|
|
475
|
-
tabs[2].click();
|
|
476
|
-
|
|
477
|
-
// After switching
|
|
478
|
-
const afterOverview = overview.style.display !== 'none';
|
|
479
|
-
const afterExamples = examples.style.display !== 'none';
|
|
480
|
-
|
|
481
|
-
return {
|
|
482
|
-
success: true,
|
|
483
|
-
initialOverview,
|
|
484
|
-
initialExamples,
|
|
485
|
-
afterOverview,
|
|
486
|
-
afterExamples
|
|
487
|
-
};
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
expect(result.success).toBe(true);
|
|
491
|
-
expect(result.afterOverview).toBe(false);
|
|
492
|
-
expect(result.afterExamples).toBe(true);
|
|
493
|
-
});
|
|
494
|
-
});
|