@bitforgehq/ui 0.3.0 → 0.3.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/CHANGELOG.md +598 -0
- package/README.md +18 -11
- package/ai/MANIFEST.index.json +306 -0
- package/ai/MANIFEST.json +8915 -3788
- package/ai/REFERENCE.index.json +476 -0
- package/ai/REFERENCE.json +5810 -2905
- package/ai/UI_GUIDE.md +212 -58
- package/ai/components/app-frame.md +328 -0
- package/ai/components/back-button.md +42 -2
- package/ai/components/badge.md +17 -7
- package/ai/components/bar-chart.md +188 -0
- package/ai/components/breadcrumb-item.md +121 -0
- package/ai/components/breadcrumb.md +277 -0
- package/ai/components/button.md +82 -15
- package/ai/components/calendar.md +300 -0
- package/ai/components/card.md +119 -4
- package/ai/components/chart-card.md +283 -0
- package/ai/components/combobox.md +411 -0
- package/ai/components/date-input.md +396 -0
- package/ai/components/datetime-input.md +215 -0
- package/ai/components/description-item.md +111 -0
- package/ai/components/description-list.md +160 -0
- package/ai/components/donut-chart.md +169 -0
- package/ai/components/empty-state.md +99 -6
- package/ai/components/header.md +71 -2
- package/ai/components/icon-button.md +74 -16
- package/ai/components/icon.md +63 -7
- package/ai/components/line-chart.md +234 -0
- package/ai/components/list.md +70 -6
- package/ai/components/menu.md +5 -0
- package/ai/components/multi-combobox.md +257 -0
- package/ai/components/nav-group.md +178 -0
- package/ai/components/nav-item.md +210 -0
- package/ai/components/page-header.md +237 -0
- package/ai/components/pagination.md +173 -0
- package/ai/components/popover.md +250 -0
- package/ai/components/side-panel.md +391 -0
- package/ai/components/sidebar-toggle.md +287 -0
- package/ai/components/sidebar.md +541 -0
- package/ai/components/skeleton.md +215 -0
- package/ai/components/sparkline.md +188 -0
- package/ai/components/stat.md +297 -0
- package/ai/components/tab-group.md +226 -0
- package/ai/components/tab-panel.md +163 -0
- package/ai/components/table.md +697 -0
- package/ai/components/tabs.md +46 -2
- package/ai/components/theme-menu-button.md +182 -0
- package/ai/components/theme-switch.md +170 -0
- package/ai/components/time-input.md +240 -0
- package/ai/components/toolbar.md +354 -0
- package/ai/components/tooltip.md +230 -0
- package/ai/components/top-nav.md +159 -0
- package/ai/reference/bf-app-frame-breakpoint.md +27 -0
- package/ai/reference/bf-app-frame-content-width.md +29 -0
- package/ai/reference/bf-badge-appearance.md +36 -0
- package/ai/reference/bf-badge-variant.md +1 -1
- package/ai/reference/bf-bar-chart-orientation.md +27 -0
- package/ai/reference/bf-button-appearance.md +36 -0
- package/ai/reference/bf-button-variant.md +1 -1
- package/ai/reference/bf-calendar-disabled-date.md +23 -0
- package/ai/reference/bf-calendar-harness.md +51 -0
- package/ai/reference/bf-calendar-weekday.md +31 -0
- package/ai/reference/bf-chart-card-heading-level.md +26 -0
- package/ai/reference/bf-chart-curve.md +28 -0
- package/ai/reference/bf-chart-harness.md +51 -0
- package/ai/reference/bf-chart-legend-position.md +30 -0
- package/ai/reference/bf-chart-series.md +23 -0
- package/ai/reference/bf-chart-value-format.md +23 -0
- package/ai/reference/bf-color-scheme-service.md +30 -0
- package/ai/reference/bf-color-scheme.md +31 -0
- package/ai/reference/bf-combobox-filter.md +27 -0
- package/ai/reference/bf-combobox-harness.md +89 -0
- package/ai/reference/bf-combobox-option.md +33 -0
- package/ai/reference/bf-compare-with.md +2 -0
- package/ai/reference/bf-date-input-harness.md +67 -0
- package/ai/reference/bf-date-input-picker.md +27 -0
- package/ai/reference/bf-date-time-input-harness.md +76 -0
- package/ai/reference/bf-date-time-input-picker.md +27 -0
- package/ai/reference/bf-description-list-layout.md +26 -0
- package/ai/reference/bf-donut-slice.md +22 -0
- package/ai/reference/bf-empty-state-heading-level.md +1 -1
- package/ai/reference/bf-empty-state-heading.md +33 -0
- package/ai/reference/bf-labels.md +73 -20
- package/ai/reference/bf-menu-button-variant.md +1 -0
- package/ai/reference/bf-menu-placement.md +1 -0
- package/ai/reference/bf-overlay-options.md +28 -27
- package/ai/reference/bf-overlay-placement.md +34 -0
- package/ai/reference/bf-overlay-position.md +1 -1
- package/ai/reference/bf-overlay-service.md +5 -3
- package/ai/reference/bf-page-header-heading-level.md +26 -0
- package/ai/reference/bf-pagination-harness.md +61 -0
- package/ai/reference/bf-platform-service.md +17 -15
- package/ai/reference/bf-popover-harness.md +42 -0
- package/ai/reference/bf-popover-placement.md +28 -0
- package/ai/reference/bf-popover-trigger-directive.md +56 -0
- package/ai/reference/bf-side-panel-config.md +35 -0
- package/ai/reference/bf-side-panel-harness.md +34 -0
- package/ai/reference/bf-side-panel-ref.md +44 -0
- package/ai/reference/bf-side-panel-service.md +43 -0
- package/ai/reference/bf-side-panel-template-context.md +32 -0
- package/ai/reference/bf-side-panel-width.md +28 -0
- package/ai/reference/bf-sidebar-state-service.md +21 -0
- package/ai/reference/bf-sidebar-toggle-harness.md +32 -0
- package/ai/reference/bf-size.md +13 -0
- package/ai/reference/bf-skeleton-shape.md +28 -0
- package/ai/reference/bf-stat-appearance.md +33 -0
- package/ai/reference/bf-stat-trend-intent.md +27 -0
- package/ai/reference/bf-stat-trend.md +27 -0
- package/ai/reference/bf-stat-variant.md +26 -0
- package/ai/reference/bf-tab-group-harness.md +44 -0
- package/ai/reference/bf-table-align.md +26 -0
- package/ai/reference/bf-table-cell-context.md +24 -0
- package/ai/reference/bf-table-cell-directive.md +22 -0
- package/ai/reference/bf-table-column.md +28 -0
- package/ai/reference/bf-table-harness.md +77 -0
- package/ai/reference/bf-table-row-key.md +21 -0
- package/ai/reference/bf-table-sort-direction.md +26 -0
- package/ai/reference/bf-table-sort.md +27 -0
- package/ai/reference/bf-table-stack.md +29 -0
- package/ai/reference/bf-theme.md +5 -4
- package/ai/reference/bf-time-input-harness.md +67 -0
- package/ai/reference/bf-time-input-hour-cycle.md +27 -0
- package/ai/reference/bf-time-input-picker.md +27 -0
- package/ai/reference/bf-tooltip-directive.md +43 -0
- package/ai/reference/bf-tooltip-harness.md +43 -0
- package/ai/reference/bf-tooltip-placement.md +28 -0
- package/ai/reference/bf_color_scheme_storage.md +20 -0
- package/ai/reference/bf_side_panel_data.md +17 -0
- package/ai/reference/bf_sidebar_state_storage.md +20 -0
- package/ai/reference/bf_theme_storage.md +3 -1
- package/ai/reference/provide-bf-color-scheme.md +20 -0
- package/ai/reference/provide-bf-labels.md +13 -4
- package/ai/reference/provide-bf-sidebar-state.md +20 -0
- package/ai/reference/slide-in-from-end.md +24 -0
- package/ai/reference/slide-out-to-end.md +24 -0
- package/bin/bf-ui.js +433 -3
- package/fesm2022/bitforgehq-ui-charts.mjs +3045 -0
- package/fesm2022/bitforgehq-ui-charts.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-icons.mjs +107 -3
- package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-mobile.mjs +14 -59
- package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-overlay.mjs +6566 -38
- package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui-testing.mjs +634 -1
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
- package/fesm2022/bitforgehq-ui.mjs +5708 -137
- package/fesm2022/bitforgehq-ui.mjs.map +1 -1
- package/llms-full.txt +26766 -14470
- package/llms.txt +106 -1
- package/package.json +7 -3
- package/theme.css +101 -0
- package/types/bitforgehq-ui-charts.d.ts +967 -0
- package/types/bitforgehq-ui-icons.d.ts +13 -1
- package/types/bitforgehq-ui-mobile.d.ts +25 -18
- package/types/bitforgehq-ui-overlay.d.ts +1895 -7
- package/types/bitforgehq-ui-testing.d.ts +782 -1
- package/types/bitforgehq-ui.d.ts +2393 -45
|
@@ -397,6 +397,639 @@ var BfDesktopToastHarness = class BfDesktopToastHarness extends ComponentHarness
|
|
|
397
397
|
await (await this.host()).sendKeys(TestKey.ESCAPE);
|
|
398
398
|
}
|
|
399
399
|
};
|
|
400
|
-
|
|
400
|
+
var BfTableHarness = class BfTableHarness extends ComponentHarness {
|
|
401
|
+
static hostSelector = "bf-table";
|
|
402
|
+
caption = this.locatorForOptional("caption");
|
|
403
|
+
headers = this.locatorForAll("thead th[data-bf-column]");
|
|
404
|
+
rows = this.locatorForAll("tbody tr[data-bf-table-row]");
|
|
405
|
+
selectAllBox = this.locatorForOptional("thead input[type=\"checkbox\"]");
|
|
406
|
+
rowBoxes = this.locatorForAll("tbody tr[data-bf-table-row] input[type=\"checkbox\"]");
|
|
407
|
+
static with(filters = {}) {
|
|
408
|
+
return new HarnessPredicate(BfTableHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
409
|
+
}
|
|
410
|
+
async getLabel() {
|
|
411
|
+
return (await (await this.caption())?.text())?.trim() ?? "";
|
|
412
|
+
}
|
|
413
|
+
async getRowCount() {
|
|
414
|
+
return (await this.rows()).length;
|
|
415
|
+
}
|
|
416
|
+
async getHeaderLabels() {
|
|
417
|
+
return Promise.all((await this.headers()).map(async (th) => (await th.text({ exclude: "[data-bf-stacked-label]" })).trim()));
|
|
418
|
+
}
|
|
419
|
+
async getCellText(row, column) {
|
|
420
|
+
const index = await this.columnIndex(column);
|
|
421
|
+
if (row < 0 || row >= await this.getRowCount()) throw new Error(`BfTableHarness: no row ${row}`);
|
|
422
|
+
return (await (await this.locatorForAll(`tbody tr[data-bf-table-row]:nth-of-type(${row + 1}) [data-bf-cell]`)())[index]?.text())?.trim() ?? "";
|
|
423
|
+
}
|
|
424
|
+
async sortBy(column) {
|
|
425
|
+
const key = await (await this.headers())[await this.columnIndex(column)]?.getAttribute("data-bf-column");
|
|
426
|
+
const button = key ? await this.locatorForOptional(`thead th[data-bf-column="${key}"] button`)() : null;
|
|
427
|
+
if (!button) throw new Error(`BfTableHarness: the column "${column}" is not sortable`);
|
|
428
|
+
await button.click();
|
|
429
|
+
}
|
|
430
|
+
async getSort() {
|
|
431
|
+
for (const header of await this.headers()) {
|
|
432
|
+
const direction = await header.getAttribute("aria-sort");
|
|
433
|
+
const column = await header.getAttribute("data-bf-column");
|
|
434
|
+
if (column && (direction === "ascending" || direction === "descending")) return {
|
|
435
|
+
column,
|
|
436
|
+
direction
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
async selectRow(index) {
|
|
442
|
+
const box = (await this.rowBoxes())[index];
|
|
443
|
+
if (!box) throw new Error(`BfTableHarness: no selectable row ${index}`);
|
|
444
|
+
await this.check(box);
|
|
445
|
+
}
|
|
446
|
+
async selectAll() {
|
|
447
|
+
const box = await this.selectAllBox();
|
|
448
|
+
if (!box) throw new Error("BfTableHarness: the table is not selectable");
|
|
449
|
+
await this.check(box);
|
|
450
|
+
}
|
|
451
|
+
async getSelectedCount() {
|
|
452
|
+
return (await Promise.all((await this.rowBoxes()).map((box) => box.getProperty("checked")))).filter(Boolean).length;
|
|
453
|
+
}
|
|
454
|
+
async check(box) {
|
|
455
|
+
if (!await box.getProperty("checked")) await box.click();
|
|
456
|
+
}
|
|
457
|
+
async columnIndex(column) {
|
|
458
|
+
const labels = await this.getHeaderLabels();
|
|
459
|
+
const index = labels.indexOf(column);
|
|
460
|
+
if (index === -1) throw new Error(`BfTableHarness: no column "${column}" (columns: ${labels.join(", ")})`);
|
|
461
|
+
return index;
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
var BfPaginationHarness = class BfPaginationHarness extends ComponentHarness {
|
|
465
|
+
static hostSelector = "bf-pagination";
|
|
466
|
+
nav = this.locatorFor("nav");
|
|
467
|
+
previousButton = this.locatorFor("[data-bf-pagination-previous]");
|
|
468
|
+
nextButton = this.locatorFor("[data-bf-pagination-next]");
|
|
469
|
+
pages = this.locatorForAll("[data-bf-pagination-page]");
|
|
470
|
+
static with(filters = {}) {
|
|
471
|
+
return new HarnessPredicate(BfPaginationHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
472
|
+
}
|
|
473
|
+
async getLabel() {
|
|
474
|
+
return await (await this.nav()).getAttribute("aria-label") ?? "";
|
|
475
|
+
}
|
|
476
|
+
async getCurrentPage() {
|
|
477
|
+
return Number(await (await this.nav()).getAttribute("data-bf-page"));
|
|
478
|
+
}
|
|
479
|
+
async getPageCount() {
|
|
480
|
+
return Number(await (await this.nav()).getAttribute("data-bf-page-count"));
|
|
481
|
+
}
|
|
482
|
+
async getVisiblePages() {
|
|
483
|
+
return Promise.all((await this.pages()).map(async (page) => Number((await page.text()).trim())));
|
|
484
|
+
}
|
|
485
|
+
async goTo(page) {
|
|
486
|
+
const [buttons, visible] = await Promise.all([this.pages(), this.getVisiblePages()]);
|
|
487
|
+
const button = buttons[visible.indexOf(page)];
|
|
488
|
+
if (!button) {
|
|
489
|
+
const shown = visible.length > 0 ? visible.join(", ") : "none";
|
|
490
|
+
throw new Error(`BfPaginationHarness: page ${page} has no button (visible: ${shown})`);
|
|
491
|
+
}
|
|
492
|
+
await button.click();
|
|
493
|
+
}
|
|
494
|
+
async next() {
|
|
495
|
+
await this.press(await this.nextButton(), "next");
|
|
496
|
+
}
|
|
497
|
+
async previous() {
|
|
498
|
+
await this.press(await this.previousButton(), "previous");
|
|
499
|
+
}
|
|
500
|
+
async isPreviousDisabled() {
|
|
501
|
+
return await (await this.previousButton()).getAttribute("aria-disabled") === "true";
|
|
502
|
+
}
|
|
503
|
+
async isNextDisabled() {
|
|
504
|
+
return await (await this.nextButton()).getAttribute("aria-disabled") === "true";
|
|
505
|
+
}
|
|
506
|
+
async press(button, name) {
|
|
507
|
+
if (await button.getAttribute("aria-disabled") === "true") throw new Error(`BfPaginationHarness: the ${name} button is disabled`);
|
|
508
|
+
await button.click();
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
const TAB = ":scope > [data-bf-tab-scroller] > [role=\"tablist\"] > [role=\"tab\"]";
|
|
512
|
+
var BfTabGroupHarness = class BfTabGroupHarness extends ComponentHarness {
|
|
513
|
+
static hostSelector = "bf-tab-group";
|
|
514
|
+
list = this.locatorFor(":scope > [data-bf-tab-scroller] > [role=\"tablist\"]");
|
|
515
|
+
tabs = this.locatorForAll(TAB);
|
|
516
|
+
tabLabels = this.locatorForAll(`${TAB} > [data-label]`);
|
|
517
|
+
panel = this.locatorForOptional(":scope > [role=\"tabpanel\"]:not([hidden])");
|
|
518
|
+
static with(filters = {}) {
|
|
519
|
+
return new HarnessPredicate(BfTabGroupHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
520
|
+
}
|
|
521
|
+
async getLabel() {
|
|
522
|
+
return await (await this.list()).getAttribute("aria-label") ?? "";
|
|
523
|
+
}
|
|
524
|
+
async getTabLabels() {
|
|
525
|
+
return Promise.all((await this.tabLabels()).map(async (label) => (await label.text()).trim()));
|
|
526
|
+
}
|
|
527
|
+
async getSelectedLabel() {
|
|
528
|
+
const [tabs, labels] = await Promise.all([this.tabs(), this.getTabLabels()]);
|
|
529
|
+
for (const [index, tab] of tabs.entries()) if (await tab.getAttribute("aria-selected") === "true") return labels[index] ?? null;
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
async selectTab(label) {
|
|
533
|
+
const [tabs, labels] = await Promise.all([this.tabs(), this.getTabLabels()]);
|
|
534
|
+
const tab = tabs[labels.indexOf(label)];
|
|
535
|
+
if (!tab) throw new Error(`BfTabGroupHarness: no tab "${label}" (tabs: ${labels.join(", ")})`);
|
|
536
|
+
if (await tab.matchesSelector(":disabled")) throw new Error(`BfTabGroupHarness: the tab "${label}" is disabled`);
|
|
537
|
+
await tab.click();
|
|
538
|
+
}
|
|
539
|
+
async getPanelText() {
|
|
540
|
+
return (await (await this.panel())?.text())?.trim() ?? "";
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
var BfSidePanelHarness = class BfSidePanelHarness extends ComponentHarness {
|
|
544
|
+
static hostSelector = "bf-side-panel";
|
|
545
|
+
title = this.locatorForOptional("[data-side-panel-header] h2");
|
|
546
|
+
closeButton = this.locatorFor("[data-side-panel-close] button");
|
|
547
|
+
static with(filters = {}) {
|
|
548
|
+
return new HarnessPredicate(BfSidePanelHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getTitle(), label));
|
|
549
|
+
}
|
|
550
|
+
async getTitle() {
|
|
551
|
+
return (await (await this.title())?.text())?.trim() ?? "";
|
|
552
|
+
}
|
|
553
|
+
async close() {
|
|
554
|
+
await (await this.closeButton()).click();
|
|
555
|
+
}
|
|
556
|
+
async isOpen() {
|
|
557
|
+
const id = await (await this.host()).getAttribute("data-bf-side-panel-id");
|
|
558
|
+
if (!id) return false;
|
|
559
|
+
return await this.documentRootLocatorFactory().locatorForOptional(`.bf-overlay-panel:not([data-bf-closing]) bf-side-panel[data-bf-side-panel-id="${id}"]`)() !== null;
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
var BfCalendarHarness = class BfCalendarHarness extends ComponentHarness {
|
|
563
|
+
static hostSelector = "bf-calendar";
|
|
564
|
+
group = this.locatorFor("[role=\"group\"]");
|
|
565
|
+
liveTitle = this.locatorFor("[aria-live=\"polite\"]");
|
|
566
|
+
titleButton = this.locatorForOptional("[data-bf-calendar-title]");
|
|
567
|
+
previousButton = this.locatorForOptional("[data-bf-calendar-previous]");
|
|
568
|
+
nextButton = this.locatorForOptional("[data-bf-calendar-next]");
|
|
569
|
+
selectedDay = this.locatorForOptional("td[data-date][aria-selected=\"true\"]");
|
|
570
|
+
dayGrid = this.locatorForOptional("table[data-bf-calendar-grid=\"day\"]");
|
|
571
|
+
static with(filters = {}) {
|
|
572
|
+
return new HarnessPredicate(BfCalendarHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
573
|
+
}
|
|
574
|
+
async getLabel() {
|
|
575
|
+
return await (await this.group()).getAttribute("aria-label") ?? "";
|
|
576
|
+
}
|
|
577
|
+
async getMonthLabel() {
|
|
578
|
+
return (await (await this.liveTitle()).text()).trim();
|
|
579
|
+
}
|
|
580
|
+
async getSelected() {
|
|
581
|
+
return await (await this.selectedDay())?.getAttribute("data-date") ?? null;
|
|
582
|
+
}
|
|
583
|
+
async nextMonth() {
|
|
584
|
+
await this.clickNav(await this.nextButton(), "next");
|
|
585
|
+
}
|
|
586
|
+
async previousMonth() {
|
|
587
|
+
await this.clickNav(await this.previousButton(), "previous");
|
|
588
|
+
}
|
|
589
|
+
async selectDate(iso) {
|
|
590
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(iso)) throw new Error(`BfCalendarHarness: "${iso}" is not an ISO date (YYYY-MM-DD)`);
|
|
591
|
+
if (!await this.dayGrid()) throw new Error("BfCalendarHarness: the calendar is not showing its days");
|
|
592
|
+
let day = await this.locatorForOptional(`td[data-date="${iso}"]`)();
|
|
593
|
+
if (!day) {
|
|
594
|
+
await this.jumpTo(iso.slice(0, 7));
|
|
595
|
+
day = await this.locatorForOptional(`td[data-date="${iso}"]`)();
|
|
596
|
+
}
|
|
597
|
+
if (!day) throw new Error(`BfCalendarHarness: no day ${iso}`);
|
|
598
|
+
if (await day.getAttribute("aria-disabled") === "true") throw new Error(`BfCalendarHarness: the day ${iso} is disabled`);
|
|
599
|
+
if (await (await this.dayGrid())?.getAttribute("aria-disabled") === "true") throw new Error("BfCalendarHarness: the calendar is disabled");
|
|
600
|
+
await day.click();
|
|
601
|
+
}
|
|
602
|
+
async jumpTo(month) {
|
|
603
|
+
const title = await this.titleButton();
|
|
604
|
+
if (!title || await title.getProperty("disabled")) throw new Error("BfCalendarHarness: the calendar is disabled");
|
|
605
|
+
await title.click();
|
|
606
|
+
await (await this.locatorFor("[data-bf-calendar-title]")()).click();
|
|
607
|
+
const year = await this.locatorForOptional(`td[data-year="${Number(month.slice(0, 4))}"]`)();
|
|
608
|
+
if (!year) throw new Error(`BfCalendarHarness: the year view does not list ${month.slice(0, 4)}`);
|
|
609
|
+
await year.click();
|
|
610
|
+
const cell = await this.locatorFor(`td[data-month="${month}"]`)();
|
|
611
|
+
if (await cell.getAttribute("aria-disabled") === "true") throw new Error(`BfCalendarHarness: the month ${month} is outside min and max`);
|
|
612
|
+
await cell.click();
|
|
613
|
+
}
|
|
614
|
+
async clickNav(button, which) {
|
|
615
|
+
if (!button) throw new Error("BfCalendarHarness: the calendar is not showing its days");
|
|
616
|
+
if (await button.getProperty("disabled") || await button.getAttribute("aria-disabled") === "true") throw new Error(`BfCalendarHarness: the ${which} month button is disabled`);
|
|
617
|
+
await button.click();
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
const FOCUSABLE = "a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
|
|
621
|
+
var BfTooltipHarness = class BfTooltipHarness extends ComponentHarness {
|
|
622
|
+
static hostSelector = "[data-bf-tooltip]";
|
|
623
|
+
inner = this.locatorForOptional(FOCUSABLE);
|
|
624
|
+
static with(filters = {}) {
|
|
625
|
+
return new HarnessPredicate(BfTooltipHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
626
|
+
}
|
|
627
|
+
async getLabel() {
|
|
628
|
+
const control = await this.control();
|
|
629
|
+
return await control.getAttribute("aria-label") ?? (await control.text()).trim();
|
|
630
|
+
}
|
|
631
|
+
async show() {
|
|
632
|
+
await (await this.control()).focus();
|
|
633
|
+
}
|
|
634
|
+
async hide() {
|
|
635
|
+
await (await this.control()).blur();
|
|
636
|
+
}
|
|
637
|
+
async isOpen() {
|
|
638
|
+
return await this.tooltip() !== null;
|
|
639
|
+
}
|
|
640
|
+
async getText() {
|
|
641
|
+
if (!await this.isOpen()) await this.show();
|
|
642
|
+
const tooltip = await this.tooltip();
|
|
643
|
+
if (!tooltip) throw new Error("BfTooltipHarness: the tooltip did not show");
|
|
644
|
+
return (await tooltip.text()).trim();
|
|
645
|
+
}
|
|
646
|
+
async control() {
|
|
647
|
+
const host = await this.host();
|
|
648
|
+
return await host.matchesSelector("a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])") ? host : await this.inner() ?? host;
|
|
649
|
+
}
|
|
650
|
+
async tooltip() {
|
|
651
|
+
const ids = (await (await this.control()).getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean);
|
|
652
|
+
const root = this.documentRootLocatorFactory();
|
|
653
|
+
for (const id of ids) {
|
|
654
|
+
const found = await root.locatorForOptional(`bf-tooltip[id="${id}"]`)();
|
|
655
|
+
if (found) return found;
|
|
656
|
+
}
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
var BfPopoverHarness = class BfPopoverHarness extends ComponentHarness {
|
|
661
|
+
static hostSelector = "[data-bf-popover-trigger]";
|
|
662
|
+
inner = this.locatorForOptional(FOCUSABLE);
|
|
663
|
+
static with(filters = {}) {
|
|
664
|
+
return new HarnessPredicate(BfPopoverHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
665
|
+
}
|
|
666
|
+
async getLabel() {
|
|
667
|
+
const control = await this.control();
|
|
668
|
+
return await control.getAttribute("aria-label") ?? (await control.text()).trim();
|
|
669
|
+
}
|
|
670
|
+
async open() {
|
|
671
|
+
if (!await this.isOpen()) await (await this.control()).click();
|
|
672
|
+
}
|
|
673
|
+
async close() {
|
|
674
|
+
await (await this.panel())?.sendKeys(TestKey.ESCAPE);
|
|
675
|
+
}
|
|
676
|
+
async isOpen() {
|
|
677
|
+
return await (await this.control()).getAttribute("aria-expanded") === "true";
|
|
678
|
+
}
|
|
679
|
+
async getPanelText() {
|
|
680
|
+
await this.open();
|
|
681
|
+
const panel = await this.panel();
|
|
682
|
+
if (!panel) throw new Error("BfPopoverHarness: the popover did not open");
|
|
683
|
+
return (await panel.text()).trim();
|
|
684
|
+
}
|
|
685
|
+
async control() {
|
|
686
|
+
const host = await this.host();
|
|
687
|
+
return await host.matchesSelector("a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])") ? host : await this.inner() ?? host;
|
|
688
|
+
}
|
|
689
|
+
async panel() {
|
|
690
|
+
const id = await (await this.control()).getAttribute("aria-controls");
|
|
691
|
+
return id ? this.documentRootLocatorFactory().locatorForOptional(`[id="${id}"]`)() : null;
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
var BfComboboxHarness = class BfComboboxHarness extends ComponentHarness {
|
|
695
|
+
static hostSelector = "bf-combobox, bf-multi-combobox";
|
|
696
|
+
input = this.locatorFor("input[role=\"combobox\"]");
|
|
697
|
+
label = this.locatorForOptional("label");
|
|
698
|
+
chips = this.locatorForAll("[data-chip]");
|
|
699
|
+
removeButtons = this.locatorForAll("[data-chip] button");
|
|
700
|
+
static with(filters = {}) {
|
|
701
|
+
return new HarnessPredicate(BfComboboxHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
702
|
+
}
|
|
703
|
+
async getLabel() {
|
|
704
|
+
const label = await this.label();
|
|
705
|
+
if (label) return (await label.text({ exclude: "[aria-hidden=\"true\"]" })).trim();
|
|
706
|
+
return await (await this.input()).getAttribute("aria-label") ?? "";
|
|
707
|
+
}
|
|
708
|
+
async open() {
|
|
709
|
+
if (!await this.isOpen()) await (await this.input()).click();
|
|
710
|
+
}
|
|
711
|
+
async close() {
|
|
712
|
+
if (await this.isOpen()) await (await this.input()).sendKeys(TestKey.ESCAPE);
|
|
713
|
+
}
|
|
714
|
+
async isOpen() {
|
|
715
|
+
return await (await this.input()).getAttribute("aria-expanded") === "true";
|
|
716
|
+
}
|
|
717
|
+
async type(query) {
|
|
718
|
+
const input = await this.input();
|
|
719
|
+
await input.focus();
|
|
720
|
+
await input.clear();
|
|
721
|
+
if (query) await input.sendKeys(query);
|
|
722
|
+
}
|
|
723
|
+
async getOptionLabels() {
|
|
724
|
+
await this.open();
|
|
725
|
+
return Promise.all((await this.options()).map(async (o) => (await o.label.text()).trim()));
|
|
726
|
+
}
|
|
727
|
+
async selectOption(label) {
|
|
728
|
+
await this.open();
|
|
729
|
+
const options = await this.options();
|
|
730
|
+
const labels = await Promise.all(options.map(async (o) => (await o.label.text()).trim()));
|
|
731
|
+
const option = options[labels.indexOf(label)];
|
|
732
|
+
if (!option) throw new Error(`BfComboboxHarness: no option "${label}" (options: ${labels.join(", ")})`);
|
|
733
|
+
if (await option.element.getAttribute("aria-disabled") === "true") throw new Error(`BfComboboxHarness: the option "${label}" is disabled`);
|
|
734
|
+
await option.element.click();
|
|
735
|
+
}
|
|
736
|
+
async getValueText() {
|
|
737
|
+
return (await this.input()).getProperty("value");
|
|
738
|
+
}
|
|
739
|
+
async getChipLabels() {
|
|
740
|
+
return Promise.all((await this.chips()).map(async (chip) => this.chipLabel(chip)));
|
|
741
|
+
}
|
|
742
|
+
async removeChip(label) {
|
|
743
|
+
const chips = await this.chips();
|
|
744
|
+
const labels = await Promise.all(chips.map(async (chip) => this.chipLabel(chip)));
|
|
745
|
+
const index = labels.indexOf(label);
|
|
746
|
+
if (index < 0) throw new Error(`BfComboboxHarness: no tag "${label}" (tags: ${labels.join(", ")})`);
|
|
747
|
+
const button = (await this.removeButtons())[index];
|
|
748
|
+
if (!button) throw new Error(`BfComboboxHarness: the tag "${label}" cannot be removed`);
|
|
749
|
+
await button.click();
|
|
750
|
+
}
|
|
751
|
+
async isDisabled() {
|
|
752
|
+
return (await this.input()).getProperty("disabled");
|
|
753
|
+
}
|
|
754
|
+
async focus() {
|
|
755
|
+
await (await this.input()).focus();
|
|
756
|
+
}
|
|
757
|
+
async blur() {
|
|
758
|
+
await (await this.input()).blur();
|
|
759
|
+
}
|
|
760
|
+
async chipLabel(chip) {
|
|
761
|
+
return (await chip.text()).trim();
|
|
762
|
+
}
|
|
763
|
+
async options() {
|
|
764
|
+
const id = await (await this.input()).getAttribute("aria-controls");
|
|
765
|
+
if (!id) return [];
|
|
766
|
+
const root = this.documentRootLocatorFactory();
|
|
767
|
+
const [elements, labels] = await Promise.all([root.locatorForAll(`[id="${id}"] [role="option"]`)(), root.locatorForAll(`[id="${id}"] [role="option"] [data-label]`)()]);
|
|
768
|
+
return elements.map((element, i) => ({
|
|
769
|
+
element,
|
|
770
|
+
label: labels[i] ?? element
|
|
771
|
+
}));
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
async function fieldLabel(field) {
|
|
775
|
+
if (field.label) return (await field.label.text({ exclude: "[aria-hidden=\"true\"]" })).trim();
|
|
776
|
+
return await (field.group ?? field.native)?.getAttribute("aria-label") ?? "";
|
|
777
|
+
}
|
|
778
|
+
async function fieldText(field) {
|
|
779
|
+
if (field.native) return field.native.getProperty("value");
|
|
780
|
+
if (!(await Promise.all(field.segments.map(async (segment) => await segment.getAttribute("aria-valuenow") !== null))).some(Boolean) || !field.group) return "";
|
|
781
|
+
return (await field.group.text()).replace(/\s+/g, " ").trim();
|
|
782
|
+
}
|
|
783
|
+
async function clearField(field) {
|
|
784
|
+
if (field.native) {
|
|
785
|
+
await field.native.clear();
|
|
786
|
+
await field.native.dispatchEvent("change");
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
for (const segment of field.segments) await segment.sendKeys(TestKey.BACKSPACE);
|
|
790
|
+
}
|
|
791
|
+
async function typeField(field, text) {
|
|
792
|
+
if (field.native) {
|
|
793
|
+
await field.native.setInputValue(text);
|
|
794
|
+
await field.native.dispatchEvent("change");
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
await clearField(field);
|
|
798
|
+
const runs = text.match(/\d+|\p{L}+/gu) ?? [];
|
|
799
|
+
for (const [index, run] of runs.entries()) {
|
|
800
|
+
const segment = field.segments[index];
|
|
801
|
+
if (!segment) throw new Error(`BfDateTimeHarness: "${text}" has more parts than the field`);
|
|
802
|
+
await segment.focus();
|
|
803
|
+
await segment.sendKeys(...run.split(""));
|
|
804
|
+
await segment.blur();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
async function openPanel(trigger) {
|
|
808
|
+
if (!trigger) throw new Error("BfDateTimeHarness: the field has no picker");
|
|
809
|
+
if (await trigger.getAttribute("aria-expanded") !== "true") {
|
|
810
|
+
if (await trigger.getProperty("disabled")) throw new Error("BfDateTimeHarness: the picker is disabled");
|
|
811
|
+
await trigger.click();
|
|
812
|
+
}
|
|
813
|
+
const id = await trigger.getAttribute("aria-controls");
|
|
814
|
+
if (!id) throw new Error("BfDateTimeHarness: the picker did not open");
|
|
815
|
+
return id;
|
|
816
|
+
}
|
|
817
|
+
async function pickPanelDate(root, panelId, iso) {
|
|
818
|
+
await (await root.locatorFor(BfCalendarHarness.with({ ancestor: `[id="${panelId}"]` }))()).selectDate(iso);
|
|
819
|
+
}
|
|
820
|
+
async function pickPanelTime(root, panelId, time) {
|
|
821
|
+
const option = await root.locatorForOptional(`[id="${panelId}"] [role="option"][data-time="${time}"]`)();
|
|
822
|
+
if (!option) throw new Error(`BfDateTimeHarness: the list has no time ${time}`);
|
|
823
|
+
if (await option.getAttribute("aria-disabled") === "true") throw new Error(`BfDateTimeHarness: the time ${time} is disabled`);
|
|
824
|
+
await option.click();
|
|
825
|
+
}
|
|
826
|
+
var BfDateInputHarness = class BfDateInputHarness extends ComponentHarness {
|
|
827
|
+
static hostSelector = "bf-date-input";
|
|
828
|
+
group = this.locatorForOptional("[role=\"group\"]");
|
|
829
|
+
nativeInput = this.locatorForOptional("input");
|
|
830
|
+
segments = this.locatorForAll("[role=\"spinbutton\"]");
|
|
831
|
+
label = this.locatorForOptional("label");
|
|
832
|
+
trigger = this.locatorForOptional("button[aria-haspopup=\"dialog\"]");
|
|
833
|
+
static with(filters = {}) {
|
|
834
|
+
return new HarnessPredicate(BfDateInputHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
835
|
+
}
|
|
836
|
+
async getLabel() {
|
|
837
|
+
return fieldLabel(await this.elements());
|
|
838
|
+
}
|
|
839
|
+
async getValue() {
|
|
840
|
+
return fieldText(await this.elements());
|
|
841
|
+
}
|
|
842
|
+
async setValue(text) {
|
|
843
|
+
await typeField(await this.elements(), text);
|
|
844
|
+
}
|
|
845
|
+
async clear() {
|
|
846
|
+
await clearField(await this.elements());
|
|
847
|
+
}
|
|
848
|
+
async isInvalid() {
|
|
849
|
+
return await (await this.nativeInput() ?? (await this.segments())[0])?.getAttribute("aria-invalid") === "true";
|
|
850
|
+
}
|
|
851
|
+
async isDisabled() {
|
|
852
|
+
const native = await this.nativeInput();
|
|
853
|
+
if (native) return native.getProperty("disabled");
|
|
854
|
+
return await (await this.group())?.getAttribute("aria-disabled") === "true";
|
|
855
|
+
}
|
|
856
|
+
async openPicker() {
|
|
857
|
+
await openPanel(await this.trigger());
|
|
858
|
+
}
|
|
859
|
+
async isPickerOpen() {
|
|
860
|
+
return await (await this.trigger())?.getAttribute("aria-expanded") === "true";
|
|
861
|
+
}
|
|
862
|
+
async pickDate(iso) {
|
|
863
|
+
const panel = await openPanel(await this.trigger());
|
|
864
|
+
await pickPanelDate(this.documentRootLocatorFactory(), panel, iso);
|
|
865
|
+
}
|
|
866
|
+
async elements() {
|
|
867
|
+
return {
|
|
868
|
+
group: await this.group(),
|
|
869
|
+
native: await this.nativeInput(),
|
|
870
|
+
segments: await this.segments(),
|
|
871
|
+
label: await this.label()
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
var BfTimeInputHarness = class BfTimeInputHarness extends ComponentHarness {
|
|
876
|
+
static hostSelector = "bf-time-input";
|
|
877
|
+
group = this.locatorForOptional("[role=\"group\"]");
|
|
878
|
+
nativeInput = this.locatorForOptional("input");
|
|
879
|
+
segments = this.locatorForAll("[role=\"spinbutton\"]");
|
|
880
|
+
label = this.locatorForOptional("label");
|
|
881
|
+
trigger = this.locatorForOptional("button[aria-haspopup=\"dialog\"]");
|
|
882
|
+
static with(filters = {}) {
|
|
883
|
+
return new HarnessPredicate(BfTimeInputHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
884
|
+
}
|
|
885
|
+
async getLabel() {
|
|
886
|
+
return fieldLabel(await this.elements());
|
|
887
|
+
}
|
|
888
|
+
async getValue() {
|
|
889
|
+
return fieldText(await this.elements());
|
|
890
|
+
}
|
|
891
|
+
async setValue(text) {
|
|
892
|
+
await typeField(await this.elements(), text);
|
|
893
|
+
}
|
|
894
|
+
async clear() {
|
|
895
|
+
await clearField(await this.elements());
|
|
896
|
+
}
|
|
897
|
+
async isInvalid() {
|
|
898
|
+
return await (await this.nativeInput() ?? (await this.segments())[0])?.getAttribute("aria-invalid") === "true";
|
|
899
|
+
}
|
|
900
|
+
async isDisabled() {
|
|
901
|
+
const native = await this.nativeInput();
|
|
902
|
+
if (native) return native.getProperty("disabled");
|
|
903
|
+
return await (await this.group())?.getAttribute("aria-disabled") === "true";
|
|
904
|
+
}
|
|
905
|
+
async openPicker() {
|
|
906
|
+
await openPanel(await this.trigger());
|
|
907
|
+
}
|
|
908
|
+
async isPickerOpen() {
|
|
909
|
+
return await (await this.trigger())?.getAttribute("aria-expanded") === "true";
|
|
910
|
+
}
|
|
911
|
+
async pickTime(time) {
|
|
912
|
+
const panel = await openPanel(await this.trigger());
|
|
913
|
+
await pickPanelTime(this.documentRootLocatorFactory(), panel, time);
|
|
914
|
+
}
|
|
915
|
+
async elements() {
|
|
916
|
+
return {
|
|
917
|
+
group: await this.group(),
|
|
918
|
+
native: await this.nativeInput(),
|
|
919
|
+
segments: await this.segments(),
|
|
920
|
+
label: await this.label()
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
var BfDateTimeInputHarness = class BfDateTimeInputHarness extends ComponentHarness {
|
|
925
|
+
static hostSelector = "bf-datetime-input";
|
|
926
|
+
group = this.locatorForOptional("[role=\"group\"]");
|
|
927
|
+
nativeInput = this.locatorForOptional("input");
|
|
928
|
+
segments = this.locatorForAll("[role=\"spinbutton\"]");
|
|
929
|
+
label = this.locatorForOptional("label");
|
|
930
|
+
trigger = this.locatorForOptional("button[aria-haspopup=\"dialog\"]");
|
|
931
|
+
static with(filters = {}) {
|
|
932
|
+
return new HarnessPredicate(BfDateTimeInputHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
933
|
+
}
|
|
934
|
+
async getLabel() {
|
|
935
|
+
return fieldLabel(await this.elements());
|
|
936
|
+
}
|
|
937
|
+
async getValue() {
|
|
938
|
+
return fieldText(await this.elements());
|
|
939
|
+
}
|
|
940
|
+
async setValue(text) {
|
|
941
|
+
await typeField(await this.elements(), text);
|
|
942
|
+
}
|
|
943
|
+
async clear() {
|
|
944
|
+
await clearField(await this.elements());
|
|
945
|
+
}
|
|
946
|
+
async isInvalid() {
|
|
947
|
+
return await (await this.nativeInput() ?? (await this.segments())[0])?.getAttribute("aria-invalid") === "true";
|
|
948
|
+
}
|
|
949
|
+
async isDisabled() {
|
|
950
|
+
const native = await this.nativeInput();
|
|
951
|
+
if (native) return native.getProperty("disabled");
|
|
952
|
+
return await (await this.group())?.getAttribute("aria-disabled") === "true";
|
|
953
|
+
}
|
|
954
|
+
async openPicker() {
|
|
955
|
+
await openPanel(await this.trigger());
|
|
956
|
+
}
|
|
957
|
+
async isPickerOpen() {
|
|
958
|
+
return await (await this.trigger())?.getAttribute("aria-expanded") === "true";
|
|
959
|
+
}
|
|
960
|
+
async pickDate(iso) {
|
|
961
|
+
const panel = await openPanel(await this.trigger());
|
|
962
|
+
await pickPanelDate(this.documentRootLocatorFactory(), panel, iso);
|
|
963
|
+
}
|
|
964
|
+
async pickTime(time) {
|
|
965
|
+
const panel = await openPanel(await this.trigger());
|
|
966
|
+
await pickPanelTime(this.documentRootLocatorFactory(), panel, time);
|
|
967
|
+
}
|
|
968
|
+
async elements() {
|
|
969
|
+
return {
|
|
970
|
+
group: await this.group(),
|
|
971
|
+
native: await this.nativeInput(),
|
|
972
|
+
segments: await this.segments(),
|
|
973
|
+
label: await this.label()
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
const LEGEND_BUTTON = "[data-bf-chart-legend] button";
|
|
978
|
+
var BfChartHarness = class BfChartHarness extends ComponentHarness {
|
|
979
|
+
static hostSelector = "bf-line-chart, bf-bar-chart, bf-donut-chart";
|
|
980
|
+
figure = this.locatorFor("figure");
|
|
981
|
+
legendButtons = this.locatorForAll(LEGEND_BUTTON);
|
|
982
|
+
dataToggle = this.locatorFor("[data-bf-chart-data-toggle]");
|
|
983
|
+
headCells = this.locatorForAll("[data-bf-chart-table] thead th");
|
|
984
|
+
bodyCells = this.locatorForAll("[data-bf-chart-table] tbody th, [data-bf-chart-table] tbody td");
|
|
985
|
+
static with(filters = {}) {
|
|
986
|
+
return new HarnessPredicate(BfChartHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
987
|
+
}
|
|
988
|
+
async getLabel() {
|
|
989
|
+
return await (await this.figure()).getAttribute("aria-label") ?? "";
|
|
990
|
+
}
|
|
991
|
+
async getSeriesNames() {
|
|
992
|
+
return Promise.all((await this.legendButtons()).map(async (button) => (await button.text()).trim()));
|
|
993
|
+
}
|
|
994
|
+
async isSeriesShown(name) {
|
|
995
|
+
return await (await this.legendButton(name)).getAttribute("aria-pressed") === "true";
|
|
996
|
+
}
|
|
997
|
+
async toggleSeries(name) {
|
|
998
|
+
await (await this.legendButton(name)).click();
|
|
999
|
+
}
|
|
1000
|
+
async showData() {
|
|
1001
|
+
const toggle = await this.dataToggle();
|
|
1002
|
+
if (await toggle.getAttribute("aria-expanded") !== "true") await toggle.click();
|
|
1003
|
+
const [head, cells] = await Promise.all([this.headCells(), this.bodyCells()]);
|
|
1004
|
+
const texts = await Promise.all(cells.map(async (cell) => (await cell.text()).trim()));
|
|
1005
|
+
const columns = Math.max(1, head.length);
|
|
1006
|
+
const rows = [];
|
|
1007
|
+
for (let i = 0; i < texts.length; i += columns) rows.push(texts.slice(i, i + columns));
|
|
1008
|
+
return rows;
|
|
1009
|
+
}
|
|
1010
|
+
async legendButton(name) {
|
|
1011
|
+
const [buttons, names] = await Promise.all([this.legendButtons(), this.getSeriesNames()]);
|
|
1012
|
+
const button = buttons[names.indexOf(name)];
|
|
1013
|
+
if (!button) throw new Error(`BfChartHarness: no series "${name}" (series: ${names.join(", ")})`);
|
|
1014
|
+
return button;
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
var BfSidebarToggleHarness = class BfSidebarToggleHarness extends ComponentHarness {
|
|
1018
|
+
static hostSelector = "bf-sidebar-toggle";
|
|
1019
|
+
button = this.locatorFor("button");
|
|
1020
|
+
static with(filters = {}) {
|
|
1021
|
+
return new HarnessPredicate(BfSidebarToggleHarness, filters).addOption("label", filters.label, async (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label));
|
|
1022
|
+
}
|
|
1023
|
+
async getLabel() {
|
|
1024
|
+
return await (await this.button()).getAttribute("aria-label") ?? "";
|
|
1025
|
+
}
|
|
1026
|
+
async isExpanded() {
|
|
1027
|
+
return await (await this.button()).getAttribute("aria-expanded") === "true";
|
|
1028
|
+
}
|
|
1029
|
+
async toggle() {
|
|
1030
|
+
await (await this.button()).click();
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
export { BfCalendarHarness, BfChartHarness, BfComboboxHarness, BfDateInputHarness, BfDateTimeInputHarness, BfDesktopToastHarness, BfDialogHarness, BfMenuButtonHarness, BfMenuHarness, BfMenuItemHarness, BfPaginationHarness, BfPopoverHarness, BfRadioGroupHarness, BfSegmentedHarness, BfSelectHarness, BfSidePanelHarness, BfSidebarToggleHarness, BfTabGroupHarness, BfTableHarness, BfTimeInputHarness, BfTooltipHarness, installBfJsdomShims, provideBfTesting };
|
|
401
1034
|
|
|
402
1035
|
//# sourceMappingURL=bitforgehq-ui-testing.mjs.map
|